Merge "Update CSIT to use Frankfurt images"
authorMorgan Richomme <morgan.richomme@orange.com>
Wed, 8 Apr 2020 12:24:50 +0000 (12:24 +0000)
committerGerrit Code Review <gerrit@onap.org>
Wed, 8 Apr 2020 12:24:50 +0000 (12:24 +0000)
216 files changed:
plans/aaf/certservice/certs/Makefile [new file with mode: 0644]
plans/aaf/certservice/docker-compose.yml
plans/aaf/certservice/setup.sh
plans/aaf/certservice/teardown.sh
plans/optf-has/has/setup.sh
plans/optf-has/has/teardown.sh
plans/optf-osdf/osdf/setup.sh
plans/optf-osdf/osdf/teardown.sh
plans/policy/pap/setup.sh
plans/usecases/pnf-sw-upgrade/cds/cds_setup.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/cds/cds_teardown.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/cds/docker-compose.yml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/cds/resources/aai.cert [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/cds/resources/application.properties [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/cds/resources/error-messages_en.properties [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/cds/resources/importCerAndStartService.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/sdn/certs/certs.properties [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/sdn/certs/keys0.zip [new file with mode: 0644]
plans/usecases/pnf-sw-upgrade/sdn/docker-compose.yml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/sdn/sdn_setup.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/sdn/sdn_teardown.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/setup.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/simulators/pnfsim/docker-compose.yml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/LICENSE [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/data.xml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/model.yang [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/subscriber.py [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/cloud-esr-system-info.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/cloud-region.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/customer.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/esr-system-info.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/esr-vnfm.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/line-of-business.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/owning-entity.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/platform.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/pnf.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/project.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/tenant.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/apply-workarounds.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/certificates/aai-certificate/aai.cert [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/distribution-test-zip/zipped_sdc_csar.tar.gz [new file with mode: 0644]
plans/usecases/pnf-sw-upgrade/so/config/env [new file with mode: 0644]
plans/usecases/pnf-sw-upgrade/so/config/override-files/api-handler-infra/onapheat/override.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/override-files/bpmn-infra/onapheat/override.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/override-files/catalog-db-adapter/onapheat/override.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/override-files/request-db-adapter/onapheat/override.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/override-files/sdc-controller/onapheat/override.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/override-files/so-monitoring/onapheat/override.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/override-files/so-vnfm-adapter/onapheat/override.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/override-files/vnfm-simulator/onapheat/override.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/populate-aai-simulator.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/wait-for-aai-config-job.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/wait-for-container.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/wait-for-workaround-job.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/config/wait-for.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/docker-compose.local.yml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/docker-compose.yml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/settings.xml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/pom.xml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/AaiSimulatorApplication.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/configration/ApplicationConfigration.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/configration/WebSecurityConfigImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/AaiSimulatorController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/BusinessController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/CloudRegionsController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/ExternalSystemEsrController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/GenericVnfsController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/LinesOfBusinessController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/NodesController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/OwningEntityController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/PlatformController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/PnfsController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/ProjectController.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/exception/InvalidRestRequestException.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/exception/RestProcessingException.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/CloudRegionKey.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/Format.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/NodeServiceInstance.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/Results.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/Clearable.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CloudRegionCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CloudRegionCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ExternalSystemCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ExternalSystemCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/GenericVnfCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/GenericVnfCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/HttpRestServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/HttpRestServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/LinesOfBusinessCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/LinesOfBusinessCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/NodesCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/NodesCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/OwnEntityCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/OwnEntityCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PlatformCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PlatformCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PnfCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PnfCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ProjectCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ProjectCacheServiceProviderImpl.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/CacheName.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/Constants.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/HttpServiceUtils.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestError.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestErrorBuilder.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestErrorResponseUtils.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/ServiceException.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/ShallowBeanCopy.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/application.yaml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/keystore/org.onap.so.p12 [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/truststore/org.onap.so.trust.jks [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/AaiSimulatorControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/AbstractSpringBootTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/BusinessControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/CloudRegionsControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/ExternalSystemEsrControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/GenericVnfsControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/LinesOfBusinessControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/NodesControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/OwningEntityControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/PlatformControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/PnfsControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/ProjectControllerTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/configuration/TestRestTemplateConfigration.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestConstants.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestRestTemplateService.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestUtils.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-customer.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-project-relation-ship.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-project.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/cloud-region-related-link.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/cloud-region.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/esr-system-info.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/esr-vnfm.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-orch-status-update.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-related-link.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-relationship.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/line-of-business-related-link.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/line-of-business.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/owning-entity-relation-ship.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/owning-entity.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/platform-related-link.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/platform.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/pnf.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/relation-ship.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-Instance-relationShip.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-instance-orch-status-update.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-instance.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-subscription.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/tenant-relationship.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/tenant.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/vServer.json [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/common/pom.xml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/cache/provider/AbstractCacheServiceProvider.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/configuration/SimulatorSecurityConfigurer.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/model/User.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/model/UserCredentials.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/common/src/test/java/org/onap/so/simulator/model/PojoClassesTest.java [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/pom.xml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/Dockerfile.so-simulator-base-image [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/Dockerfile.workaround-job-container [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/configs/logging/logback-spring.xml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/scripts/start-app.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/package/pom.xml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/simulator/pom.xml [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/so_setup.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/so/so_teardown.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/teardown.sh [new file with mode: 0755]
plans/usecases/pnf-sw-upgrade/test.properties [new file with mode: 0644]
plans/usecases/pnf-sw-upgrade/testplan.txt [new file with mode: 0644]
run-csit.sh
scripts/optf-has/has/has-properties/conductor.conf.onap
scripts/optf-has/has/has_script.sh
scripts/optf-has/has/setup-sms.sh [new file with mode: 0755]
scripts/optf-osdf/osdf/osdf-properties/osdf.json
scripts/optf-osdf/osdf/osdf-properties/osdf_config.yaml
scripts/optf-osdf/osdf/osdf_script.sh
scripts/optf-osdf/osdf/setup-sms.sh [new file with mode: 0755]
scripts/policy/config/drools-apps/custom/noop.pre.sh
scripts/policy/config/drools-apps/env/base.conf
scripts/policy/config/drools/env/base.conf
scripts/policy/config/pap/onap.policies.monitoring.cdap.tca.hi.lo.app.json [deleted file]
scripts/policy/docker-compose-api.yml
scripts/policy/docker-compose-pap.yml
scripts/policy/policy-xacml-pdp/docker-compose-pdpx.yml
scripts/sdc/setup_sdc_for_sanity.sh
tests/aaf/certservice/assets/invalid_client_docker.env
tests/aaf/certservice/assets/valid_client_docker.env
tests/aaf/certservice/cert-service-test.robot
tests/aaf/certservice/libraries/CertClientManager.py
tests/aaf/certservice/libraries/EnvsReader.py [new file with mode: 0644]
tests/aaf/certservice/libraries/JksFilesValidator.py [new file with mode: 0644]
tests/aaf/certservice/resources/cert-service-keywords.robot
tests/aaf/certservice/resources/cert-service-properties.robot
tests/dcaegen2/testcases/assets/json_events/CommonEventFormat_28.3.json [deleted file]
tests/dcaegen2/testcases/assets/json_events/CommonEventFormat_30.1.1.json [new file with mode: 0644]
tests/dcaegen2/testcases/dcae_ves.robot
tests/dcaegen2/testcases/resources/DMaaP.py
tests/dcaegen2/testcases/resources/DcaeVariables.py
tests/dcaegen2/testcases/resources/dcae_keywords.robot
tests/optf-osdf/osdf/optf_osdf_test.robot
tests/policy/drools-applications/drools-applications-test.robot
tests/policy/pap/data/vCPE.policy.monitoring.input.tosca.json [moved from scripts/policy/config/pap/vCPE.policy.monitoring.input.tosca.json with 100% similarity]
tests/policy/pap/pap-test.robot
tests/sdc-dcae-d/dcaed/monitoring_configuration_service_test.robot
tests/usecases/pnf-sw-upgrade/.gitignore [new file with mode: 0755]
tests/usecases/pnf-sw-upgrade/__init__.robot [new file with mode: 0644]
tests/usecases/pnf-sw-upgrade/data/blueprint_archive.zip [new file with mode: 0644]
tests/usecases/pnf-sw-upgrade/data/distributeServiceTemplate.json [new file with mode: 0644]
tests/usecases/pnf-sw-upgrade/data/mount.json [new file with mode: 0755]
tests/usecases/pnf-sw-upgrade/data/serviceInstantiationActivationRequest.json [new file with mode: 0644]
tests/usecases/pnf-sw-upgrade/data/serviceInstantiationDownloadRequest.json [new file with mode: 0644]
tests/usecases/pnf-sw-upgrade/pnf-sw-upgrade.robot [new file with mode: 0644]

diff --git a/plans/aaf/certservice/certs/Makefile b/plans/aaf/certservice/certs/Makefile
new file mode 100644 (file)
index 0000000..126e053
--- /dev/null
@@ -0,0 +1,110 @@
+all: step_1 step_2 step_3 step_4 step_5 step_6 step_7 step_8 step_9 step_10 step_11 step_12 step_13 step_14 step_15
+.PHONY: all
+#Clear certificates
+clear:
+       @echo "Clear certificates"
+       rm -f certServiceClient-keystore.jks certServiceServer-keystore.jks root.crt truststore.jks certServiceServer-keystore.p12
+       @echo "#####done#####"
+
+#Generate root private and public keys
+step_1:
+       @echo "Generate root private and public keys"
+       keytool -genkeypair -v -alias root -keyalg RSA -keysize 4096 -validity 3650 -keystore root-keystore.jks \
+    -dname "CN=root.com, OU=Root Org, O=Root Company, L=Wroclaw, ST=Dolny Slask, C=PL" -keypass secret \
+    -storepass secret -ext BasicConstraints:critical="ca:true"
+       @echo "#####done#####"
+
+#Export public key as certificate
+step_2:
+       @echo "(Export public key as certificate)"
+       keytool -exportcert -alias root -keystore root-keystore.jks -storepass secret -file root.crt -rfc
+       @echo "#####done#####"
+
+#Self-signed root (import root certificate into truststore)
+step_3:
+       @echo "(Self-signed root (import root certificate into truststore))"
+       keytool -importcert -alias root -keystore truststore.jks -file root.crt -storepass secret -noprompt
+       @echo "#####done#####"
+
+#Generate certService's client private and public keys
+step_4:
+       @echo "Generate certService's client private and public keys"
+       keytool -genkeypair -v -alias certServiceClient -keyalg RSA -keysize 2048 -validity 730 \
+    -keystore certServiceClient-keystore.jks -storetype JKS \
+    -dname "CN=certServiceClient.com,OU=certServiceClient company,O=certServiceClient org,L=Wroclaw,ST=Dolny Slask,C=PL" \
+    -keypass secret -storepass secret
+       @echo "####done####"
+
+#Generate certificate signing request for certService's client
+step_5:
+       @echo "Generate certificate signing request for certService's client"
+       keytool -certreq -keystore certServiceClient-keystore.jks -alias certServiceClient -storepass secret -file certServiceClient.csr
+       @echo "####done####"
+
+#Sign certService's client certificate by root CA
+step_6:
+       @echo "Sign certService's client certificate by root CA"
+       keytool -gencert -v -keystore root-keystore.jks -storepass secret -alias root -infile certServiceClient.csr \
+    -outfile certServiceClientByRoot.crt -rfc -ext bc=0  -ext ExtendedkeyUsage="serverAuth,clientAuth"
+       @echo "####done####"
+
+#Import root certificate into client
+step_7:
+       @echo "Import root certificate into intermediate"
+       cat root.crt >> certServiceClientByRoot.crt
+       @echo "####done####"
+
+#Import signed certificate into certService's client
+step_8:
+       @echo "Import signed certificate into certService's client"
+       keytool -importcert -file certServiceClientByRoot.crt -destkeystore certServiceClient-keystore.jks -alias certServiceClient -storepass secret -noprompt
+       @echo "####done####"
+
+#Generate certService private and public keys
+step_9:
+       @echo "Generate certService private and public keys"
+       keytool -genkeypair -v -alias aaf-cert-service -keyalg RSA -keysize 2048 -validity 730 \
+    -keystore certServiceServer-keystore.jks -storetype JKS \
+    -dname "CN=aaf-cert-service,OU=certServiceServer company,O=certServiceServer org,L=Wroclaw,ST=Dolny Slask,C=PL" \
+    -keypass secret -storepass secret -ext BasicConstraints:critical="ca:false"
+       @echo "####done####"
+
+#Generate certificate signing request for certService
+step_10:
+       @echo "Generate certificate signing request for certService"
+       keytool -certreq -keystore certServiceServer-keystore.jks -alias aaf-cert-service -storepass secret -file certServiceServer.csr
+       @echo "####done####"
+
+#Sign certService certificate by root CA
+step_11:
+       @echo "Sign certService certificate by root CA"
+       keytool -gencert -v -keystore root-keystore.jks -storepass secret -alias root -infile certServiceServer.csr \
+    -outfile certServiceServerByRoot.crt -rfc -ext bc=0  -ext ExtendedkeyUsage="serverAuth,clientAuth" \
+    -ext SubjectAlternativeName:="DNS:aaf-cert-service,DNS:localhost"
+       @echo "####done####"
+
+#Import root certificate into server
+step_12:
+       @echo "Import root certificate into intermediate(server)"
+       cat root.crt >> certServiceServerByRoot.crt
+       @echo "####done####"
+
+#Import signed certificate into certService
+step_13:
+       @echo "Import signed certificate into certService"
+       keytool -importcert -file certServiceServerByRoot.crt -destkeystore certServiceServer-keystore.jks -alias aaf-cert-service \
+    -storepass secret -noprompt
+       @echo "####done####"
+
+#Convert certServiceServer-keystore(.jks) to PCKS12 format(.p12)
+step_14:
+       @echo "Convert certServiceServer-keystore(.jks) to PCKS12 format(.p12)"
+       keytool -importkeystore -srckeystore certServiceServer-keystore.jks -srcstorepass secret \
+        -destkeystore certServiceServer-keystore.p12 -deststoretype PKCS12 -deststorepass secret
+       @echo "#####done#####"
+
+#Clear unused certificates
+step_15:
+       @echo "Clear unused certificates"
+       rm -f certServiceClientByRoot.crt certServiceClient.csr root-keystore.jks certServiceServerByRoot.crt  certServiceServer.csr
+       @echo "#####done#####"
index ae7ee87..dcac7df 100644 (file)
@@ -10,9 +10,6 @@ services:
       - "443:8443"
     volumes:
       - $SCRIPTS_PATH:/opt/primekey/scripts
-    command: bash -c "
-      /opt/primekey/bin/start.sh
-      "
     healthcheck:
       test: ["CMD-SHELL", "curl -kI https://localhost:8443/ejbca/publicweb/healthcheck/ejbcahealth"]
       interval: 20s
@@ -21,16 +18,25 @@ services:
     networks:
       - certservice
 
-  certservice:
+  aaf-cert-service:
     image: nexus3.onap.org:10001/onap/org.onap.aaf.certservice.aaf-certservice-api:latest
     volumes:
       - $CONFIGURATION_PATH:/etc/onap/aaf/certservice/cmpServers.json
-    container_name: aafcert
+      - ./certs/truststore.jks:/etc/onap/aaf/certservice/certs/truststore.jks
+      - ./certs/root.crt:/etc/onap/aaf/certservice/certs/root.crt
+      - ./certs/certServiceServer-keystore.jks:/etc/onap/aaf/certservice/certs/certServiceServer-keystore.jks
+      - ./certs/certServiceServer-keystore.p12:/etc/onap/aaf/certservice/certs/certServiceServer-keystore.p12
+    container_name: aafcert-service
     ports:
-      - "8080:8080"
+      - "8443:8443"
     depends_on:
       ejbca:
         condition: service_healthy
+    healthcheck:
+      test: ["CMD-SHELL", "curl https://localhost:8443/actuator/health --cacert /etc/onap/aaf/certservice/certs/root.crt --cert-type p12 --cert /etc/onap/aaf/certservice/certs/certServiceServer-keystore.p12 --pass secret"]
+      interval: 10s
+      timeout: 3s
+      retries: 15
     networks:
       - certservice
 
index 250b92a..b23b719 100644 (file)
@@ -35,6 +35,11 @@ pip uninstall -y docker-py
 pip uninstall -y docker
 pip install -U docker==2.7.0
 
+#reinstall pyopenssl library
+echo "Reinstall pyopenssl library."
+pip uninstall pyopenssl -y
+pip install pyopenssl==17.5.0
+
 #Disable proxy - for local run
 unset http_proxy https_proxy
 
@@ -66,15 +71,26 @@ echo "Use configuration from: $CONFIGURATION_PATH"
 export CONFIGURATION_PATH=${CONFIGURATION_PATH}
 export SCRIPTS_PATH=${SCRIPTS_PATH}
 
+#Generate keystores, truststores, certificates and keys
+mkdir -p ${WORKSPACE}/tests/aaf/certservice/assets/certs/
+make all -C ./certs/
+cp ${WORKSPACE}/plans/aaf/certservice/certs/root.crt ${WORKSPACE}/tests/aaf/certservice/assets/certs/root.crt
+echo "Generated keystores"
+openssl pkcs12 -in ${WORKSPACE}/plans/aaf/certservice/certs/certServiceServer-keystore.p12 -clcerts -nokeys -password pass:secret | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ${WORKSPACE}/tests/aaf/certservice/assets/certs/certServiceServer.crt
+echo "Generated server certificate"
+openssl pkcs12 -in ${WORKSPACE}/plans/aaf/certservice/certs/certServiceServer-keystore.p12 -nocerts -nodes -password pass:secret| sed -ne '/-BEGIN PRIVATE KEY-/,/-END PRIVATE KEY-/p' > ${WORKSPACE}/tests/aaf/certservice/assets/certs/certServiceServer.key
+echo "Generated server key"
+
 docker-compose up -d
 
 AAFCERT_IP='none'
 # Wait container ready
 for i in {1..9}
 do
-   AAFCERT_IP=`get-instance-ip.sh aafcert`
-   RESP_CODE=$(curl -I -s -o /dev/null -w "%{http_code}"  http://${AAFCERT_IP}:8080/actuator/health)
-   if [[ "$RESP_CODE" == '200' ]]; then
+   AAFCERT_IP=`get-instance-ip.sh aafcert-service`
+   RESP_CODE=$(curl -s https://localhost:8443/actuator/health --cacert ./certs/root.crt --cert-type p12 --cert ./certs/certServiceServer-keystore.p12 --pass secret | \
+   python2 -c 'import json,sys;obj=json.load(sys.stdin);print obj["status"]')
+   if [[ "$RESP_CODE" == "UP" ]]; then
        echo 'AAF Cert Service is ready'
        export AAFCERT_IP=${AAFCERT_IP}
        docker exec aafcert-ejbca /opt/primekey/scripts/ejbca-configuration.sh
index 83737f0..71e20b7 100644 (file)
@@ -17,4 +17,9 @@
 
 docker-compose down
 
+make clear -C ./certs/
+echo "Removed old keystores"
+rm -rf ${WORKSPACE}/tests/aaf/certservice/assets/certs
+echo "Removed old certificates"
+
 kill-instance.sh ${ClientContainerName}
\ No newline at end of file
index 593a686..db3ec7c 100755 (executable)
@@ -15,7 +15,7 @@
 # limitations under the License.
 #
 echo "# aaf-sms setup.sh script";
-source ${WORKSPACE}/plans/aaf/sms-test-plan/setup.sh
+source ${WORKSPACE}/scripts/optf-has/has/setup-sms.sh
 
 #
 # add here eventual scripts needed for music
index 477c7ed..0b2b629 100755 (executable)
@@ -33,5 +33,6 @@ echo "# optf/has music scripts calling";
 source ${WORKSPACE}/scripts/optf-has/has/music_teardown_script.sh
 
 echo "# aaf-sms teardown.sh script";
-source ${WORKSPACE}/plans/aaf/sms-test-plan/teardown.sh
+kill-instance.sh sms
+kill-instance.sh vault
 
index d2d45af..42e9aec 100755 (executable)
@@ -20,7 +20,7 @@
 
 #
 echo "# aaf-sms setup.sh script";
-source ${WORKSPACE}/plans/aaf/sms-test-plan/setup.sh
+source ${WORKSPACE}/scripts/optf-osdf/osdf/setup-sms.sh
 
 echo "# simulator scripts calling";
 source ${WORKSPACE}/scripts/optf-osdf/osdf/simulator_script.sh
index cae8dcc..3457295 100755 (executable)
@@ -31,5 +31,6 @@ kill-instance.sh optf-osdf
 kill-instance.sh osdf_sim
 
 echo "# aaf-sms teardown.sh script";
-source ${WORKSPACE}/plans/aaf/sms-test-plan/teardown.sh
+kill-instance.sh sms
+kill-instance.sh vault
 
index 8a613bc..a5350b2 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/bash
 # ============LICENSE_START=======================================================
 #  Copyright (C) 2019 Nordix Foundation.
-#  Modifications Copyright (C) 2019 AT&T Intellectual Property.
+#  Modifications Copyright (C) 2019-2020 AT&T Intellectual Property.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -57,19 +57,6 @@ echo PAP IP IS ${POLICY_PAP_IP}
 echo API IP IS ${POLICY_API_IP}
 echo MARIADB IP IS ${MARIADB_IP}
 
-#Add policy type and policy to the database via the Policy Api
-AUTH="healthcheck:zb!XztG34"
-CONTYPE="Content-Type: application/json"
-URL=https://${POLICY_API_IP}:6969/policy/api/v1/policytypes
-CONFIGDIR=${WORKSPACE}/scripts/policy/config/pap
-POLTYPE=onap.policies.monitoring.cdap.tca.hi.lo.app
-
-SRCFILE=${CONFIGDIR}/${POLTYPE}.json
-curl -sS -k --user "${AUTH}" -H "${CONTYPE}" -d @${SRCFILE} $URL
-
-URL2=${URL}/${POLTYPE}/versions/1.0.0/policies
-SRCFILE=${CONFIGDIR}/vCPE.policy.monitoring.input.tosca.json
-curl -sS -k --user "${AUTH}" -H "${CONTYPE}" -d @${SRCFILE} $URL2
-
-
-ROBOT_VARIABLES="-v POLICY_PAP_IP:${POLICY_PAP_IP}"
+ROBOT_VARIABLES=""
+ROBOT_VARIABLES="${ROBOT_VARIABLES} -v POLICY_PAP_IP:${POLICY_PAP_IP}"
+ROBOT_VARIABLES="${ROBOT_VARIABLES} -v POLICY_API_IP:${POLICY_API_IP}"
diff --git a/plans/usecases/pnf-sw-upgrade/cds/cds_setup.sh b/plans/usecases/pnf-sw-upgrade/cds/cds_setup.sh
new file mode 100755 (executable)
index 0000000..b6b4610
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#   Copyright (C) 2020 Nordix Foundation.
+# ================================================================================
+#  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.
+#
+#  SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+# @author Rahul Tyagi (rahul.tyagi@est.tech)
+
+CDS_DATA_PATH=$WORKSPACE/plans/$PARENT/$SUB_PARENT/cds
+
+cd $CDS_DATA_PATH
+export CDS_DOCKER_PATH=$CDS_DOCKER_PATH
+export APP_CONFIG_HOME=$APP_CONFIG_HOME
+
+docker pull $NEXUS_DOCKER_REPO/onap/ccsdk-blueprintsprocessor:$BP_IMAGE_TAG
+docker tag $NEXUS_DOCKER_REPO/onap/ccsdk-blueprintsprocessor:$BP_IMAGE_TAG onap/ccsdk-blueprintsprocessor:latest
+
+docker-compose -f $CDS_DATA_PATH/docker-compose.yml -p $PROJECT_NAME up -d 
+sleep 10
+################# Check state of BP ####################
+BP_CONTAINER=$(docker ps -a -q --filter="name=bp-rest")
+CCSDK_MARIADB=$(docker ps -a -q --filter="name=ccsdk-mariadb")
+for i in {1..10}; do
+if [ $(docker inspect --format='{{ .State.Running }}' $BP_CONTAINER) ]
+then
+   echo "Blueprint proc Service Running"
+   break
+else
+   echo sleep $i
+   sleep $i
+fi
+done
+
diff --git a/plans/usecases/pnf-sw-upgrade/cds/cds_teardown.sh b/plans/usecases/pnf-sw-upgrade/cds/cds_teardown.sh
new file mode 100755 (executable)
index 0000000..9f2ac53
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+DOCKER_COMPOSE_FILE_PATH=$SCRIPT_HOME/docker-compose.yml
+
+echo "Tearing down docker containers from remote images ..."
+docker-compose -f $DOCKER_COMPOSE_FILE_PATH -p $PROJECT_NAME down
diff --git a/plans/usecases/pnf-sw-upgrade/cds/docker-compose.yml b/plans/usecases/pnf-sw-upgrade/cds/docker-compose.yml
new file mode 100755 (executable)
index 0000000..6fbde12
--- /dev/null
@@ -0,0 +1,38 @@
+version: '3.3'
+
+services:
+  db:
+    image: mariadb:latest
+    container_name: ccsdk-mariadb
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ~/vm_mysql:/var/lib/mysql
+    restart: always
+    environment:
+      MYSQL_ROOT_PASSWORD: sdnctl
+      MYSQL_DATABASE: sdnctl
+      MYSQL_USER: sdnctl
+      MYSQL_PASSWORD: sdnctl
+  blueprints-processor:
+    image: onap/ccsdk-blueprintsprocessor:latest
+    depends_on:
+      - db
+    ports:
+      - "8000:8080"
+    restart: always
+    container_name: bp-rest
+    environment:
+      - APPLICATIONNAME=BlueprintsProcessor
+      - BUNDLEVERSION=1.0.0
+      - APP_CONFIG_HOME=/opt/app/onap/config
+      - ENVCONTEXT=dev
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${WORKSPACE}/plans/usecases/pnf-sw-upgrade/cds/resources:/opt/app/onap/res
+    entrypoint: 
+      - /bin/sh
+      - -c 
+      - "/opt/app/onap/res/importCerAndStartService.sh"
+    extra_hosts:
+      - sdnc:${LOCAL_IP}
+      - aai-simulator:${LOCAL_IP}
diff --git a/plans/usecases/pnf-sw-upgrade/cds/resources/aai.cert b/plans/usecases/pnf-sw-upgrade/cds/resources/aai.cert
new file mode 100755 (executable)
index 0000000..9acb8bb
--- /dev/null
@@ -0,0 +1,31 @@
+Bag Attributes
+    friendlyName: so@so.onap.org
+    localKeyID: 54 69 6D 65 20 31 35 36 34 30 35 32 33 31 34 37 38 34 
+subject=CN = aai-simulator, emailAddress = , OU = so@so.onap.org, OU = OSAAF, O = ONAP, C = US
+
+issuer=C = US, O = ONAP, OU = OSAAF, CN = intermediateCA_9
+
+-----BEGIN CERTIFICATE-----
+MIIEBzCCAu+gAwIBAgIIdC1kel7DdnYwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UE
+BhMCVVMxDTALBgNVBAoMBE9OQVAxDjAMBgNVBAsMBU9TQUFGMRkwFwYDVQQDDBBp
+bnRlcm1lZGlhdGVDQV85MB4XDTE5MDcyNTEwNTgzNFoXDTIwMDcyNTEwNTgzNFow
+bjEWMBQGA1UEAwwNYWFpLXNpbXVsYXRvcjEPMA0GCSqGSIb3DQEJARYAMRcwFQYD
+VQQLDA5zb0Bzby5vbmFwLm9yZzEOMAwGA1UECwwFT1NBQUYxDTALBgNVBAoMBE9O
+QVAxCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+185xCE6cmsY6XB5Dd/5GlfuWjN05KKk3akymxhbJLa9ektlusmuTPt4cnxD+e4b6
+dymqHzQ6C206TBK1jaDzcF07Ag7VTpxmlgaSukQ+aZoXfIcs80lWCLnNvC2MrOuh
+9uhUILAmuddo01cIHJvti5R2g6BEirCGsVKBSwmXRotxHyzUg9IwOpeGy0G1ZDjU
+OiMqY5qOonVTEz1AganctdiWK1/eZ5IBD7gQwckS5n1a6RYMVSnr1vKLoiZq76Bp
+wKy3EBX16jlmQMC5Aj9/GDezJg0bPvlikL3VUsC76DRShucsxS3SzVxeAJ5nsH8S
+qUElpbe3uabhFG2qKmtvdwIDAQABo4HPMIHMMAkGA1UdEwQCMAAwDgYDVR0PAQH/
+BAQDAgXgMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBUBgNVHSME
+TTBLgBSB95lbELnIjN7zUl7qTmmgQz6s3aEwpC4wLDEOMAwGA1UECwwFT1NBQUYx
+DTALBgNVBAoMBE9OQVAxCzAJBgNVBAYTAlVTggEHMB0GA1UdDgQWBBSQ54p+SID0
+2p21lUHY9YC1ZZfkZTAYBgNVHREEETAPgg1hYWktc2ltdWxhdG9yMA0GCSqGSIb3
+DQEBCwUAA4IBAQBRGK6Iyjc/0bC3+qjPuNwSlu1pUcgHtgxP/oTU5f9xMSkSjIP0
+weVnIEGOwlW8GRbDPQza14AHETTxJ17rv6p6h7l/dZZmbMPl2S+QXGptgDWR6zY7
+q5ROecGcQzgto6lTMcKgBMW+ct3Tb3khMqP6ewzGz85SY7BgyVE7HFG9M5BM3NhX
+ovAcj93C24DFKLDKxHrrsVIROlFk6QW2+kb0zo1YzVc6NNJY2ViXBrM5zrG21tDj
+VEv0JaHKPYhzWCb7ZcSSo/ftZ2yDsRGS8r6DK5sYCfLifloMVJhF04hOC+ZbxiiB
+JgYniQPmb0Zj5BfXWovdAe/89wr5aokQ3GZL
+-----END CERTIFICATE-----
diff --git a/plans/usecases/pnf-sw-upgrade/cds/resources/application.properties b/plans/usecases/pnf-sw-upgrade/cds/resources/application.properties
new file mode 100755 (executable)
index 0000000..d11bab6
--- /dev/null
@@ -0,0 +1,123 @@
+# Web server config
+### START -Controller Blueprints Properties
+# Load Resource Source Mappings
+resourceSourceMappings=processor-db=source-db,input=source-input,default=source-default,sdnc=source-rest,aai-data=source-rest,capability=source-capability,rest=source-rest,vault-data=source-rest,script=source-capability
+
+# Controller Blueprints Core Configuration
+blueprintsprocessor.blueprintDeployPath=/opt/app/onap/blueprints/deploy
+blueprintsprocessor.blueprintArchivePath=/opt/app/onap/blueprints/archive
+blueprintsprocessor.blueprintWorkingPath=/opt/app/onap/blueprints/working
+
+# Controller Blueprint Load Configurations
+blueprintsprocessor.loadBluePrintPaths=/opt/app/onap/model-catalog/blueprint-model
+blueprintsprocessor.loadModeTypePaths=/opt/app/onap/model-catalog/definition-type
+blueprintsprocessor.loadResourceDictionaryPaths=/opt/app/onap/model-catalog/resource-dictionary
+
+# CBA file extension
+controllerblueprints.loadCbaExtension=zip
+
+### END -Controller Blueprints Properties
+
+blueprintsprocessor.grpcEnable=true
+blueprintsprocessor.httpPort=8080
+blueprintsprocessor.grpcPort=9111
+
+# db
+blueprintsprocessor.db.url=jdbc:mysql://db:3306/sdnctl
+blueprintsprocessor.db.username=sdnctl
+blueprintsprocessor.db.password=sdnctl
+blueprintsprocessor.db.driverClassName=org.mariadb.jdbc.Driver
+blueprintsprocessor.db.hibernateHbm2ddlAuto=update
+blueprintsprocessor.db.hibernateDDLAuto=update
+blueprintsprocessor.db.hibernateNamingStrategy=org.hibernate.cfg.ImprovedNamingStrategy
+blueprintsprocessor.db.hibernateDialect=org.hibernate.dialect.MySQL5InnoDBDialect
+
+# processor-db endpoint
+blueprintsprocessor.db.processor-db.type=maria-db
+blueprintsprocessor.db.processor-db.url=jdbc:mysql://mariadb-galera:3306/sdnctl
+blueprintsprocessor.db.processor-db.username=root
+blueprintsprocessor.db.processor-db.password=secretpassword
+
+# Python executor
+blueprints.processor.functions.python.executor.executionPath=/opt/app/onap/scripts/jython/ccsdk_blueprints
+blueprints.processor.functions.python.executor.modulePaths=/opt/app/onap/scripts/jython/ccsdk_blueprints,/opt/app/onap/scripts/jython/ccsdk_netconf,/opt/app/onap/scripts/jython/ccsdk_restconf
+
+security.user.password: {bcrypt}$2a$10$duaUzVUVW0YPQCSIbGEkQOXwafZGwQ/b32/Ys4R1iwSSawFgz7QNu
+security.user.name: ccsdkapps
+
+# Used in Health Check
+#endpoints.user.name=ccsdkapps
+#endpoints.user.password=ccsdkapps
+
+# Executor Options
+blueprintsprocessor.resourceResolution.enabled=true
+blueprintsprocessor.netconfExecutor.enabled=true
+blueprintsprocessor.restConfExecutor.enabled=true
+blueprintsprocessor.cliExecutor.enabled=true
+blueprintsprocessor.remoteScriptCommand.enabled=true
+
+# Command executor
+blueprintsprocessor.grpcclient.remote-python.type=token-auth
+blueprintsprocessor.grpcclient.remote-python.host=localhost
+blueprintsprocessor.grpcclient.remote-python.port=50051
+blueprintsprocessor.grpcclient.remote-python.token=Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==
+
+# Py executor
+blueprintsprocessor.grpcclient.py-executor.type=tls-auth
+blueprintsprocessor.grpcclient.py-executor.host=py-executor-default:50052
+blueprintsprocessor.grpcclient.py-executor.trustCertCollection=/opt/app/onap/config/certs/py-executor/py-executor-chain.pem
+
+# Config Data REST client settings
+blueprintsprocessor.restconfEnabled=true
+blueprintsprocessor.restclient.sdnc.type=basic-auth
+blueprintsprocessor.restclient.sdnc.url=http://sdnc:8282
+blueprintsprocessor.restclient.sdnc.username=admin
+blueprintsprocessor.restclient.sdnc.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
+
+# Primary AAI Data REST Client settings
+blueprintsprocessor.restclient.aai-data.type=basic-auth
+blueprintsprocessor.restclient.aai-data.url=https://aai-simulator:9993
+blueprintsprocessor.restclient.aai-data.username=aai@aai.onap.org
+blueprintsprocessor.restclient.aai-data.password=demo123456!
+blueprintsprocessor.restclient.aai-data.additionalHeaders.X-TransactionId=cds-transaction-id
+blueprintsprocessor.restclient.aai-data.additionalHeaders.X-FromAppId=cds-app-id
+blueprintsprocessor.restclient.aai-data.additionalHeaders.Accept=application/json
+
+# Kafka-message-lib Configuration
+blueprintsprocessor.messageconsumer.self-service-api.kafkaEnable=false
+blueprintsprocessor.messageconsumer.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageconsumer.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t
+blueprintsprocessor.messageconsumer.self-service-api.groupId=receiver-id
+blueprintsprocessor.messageconsumer.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=1000
+
+blueprintsprocessor.messageproducer.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageproducer.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageproducer.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageproducer.self-service-api.topic=producer.t
+
+
+blueprintprocessor.remoteScriptCommand.enabled=true
+
+#Encrypted username and password for health check service
+endpoints.user.name=eHbVUbJAj4AG2522cSbrOQ==
+endpoints.user.password=eHbVUbJAj4AG2522cSbrOQ==
+
+#BaseUrls for health check blueprint processor services
+blueprintprocessor.healthcheck.baseUrl=http://localhost:8080/
+blueprintprocessor.healthcheck.mapping-service-name-with-service-link=[Execution service,/api/v1/execution-service/health-check],[Resources service,/api/v1/resources/health-check],[Template service,/api/v1/template/health-check]
+
+#BaseUrls for health check Cds Listener services
+cdslistener.healthcheck.baseUrl=http://cds-sdc-listener:8080/
+cdslistener.healthcheck.mapping-service-name-with-service-link=[SDC Listener service,/api/v1/sdclistener/healthcheck]
+
+#Actuator properties
+management.endpoints.web.exposure.include=*
+management.endpoint.health.show-details=always
+management.info.git.mode=full
+
+# Error Managements
+error.catalog.applicationId=cds
+error.catalog.type=properties
+error.catalog.errorDefinitionDir=/opt/app/onap/config/
diff --git a/plans/usecases/pnf-sw-upgrade/cds/resources/error-messages_en.properties b/plans/usecases/pnf-sw-upgrade/cds/resources/error-messages_en.properties
new file mode 100755 (executable)
index 0000000..71196ce
--- /dev/null
@@ -0,0 +1,91 @@
+#
+# Copyright © 2020 IBM, Bell Canada
+#
+# 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.
+#
+org.onap.ccsdk.cds.blueprintsprocessor.generic_failure=cause=Internal error in Blueprint Processor run time.,action=Contact CDS administrator team.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Self Service API
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.generic_failure=cause=Internal error in Self Service API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.generic_process_failure=cause=Internal error while processing REST call to the Self Service API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Designer API
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.generic_failure=cause=Internal error while processing REST call to the Designer API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.designer.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+# Resource API
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.generic_failure=cause=Internal error while processing REST call to the Resource API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.invalid_file_extension=cause=Failed trying to upload a non ZIP file format.,action=Please reload your file and make sure it is in ZIP format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_writing_fail=cause=Fail to write resources files.,action=Please reload your files and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.api.unsupported_media_type=cause=An invalid media was provided.,action=Please make sure your media or artifact is in the proper structure or format.
+
+
+# Configs API
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.generic_failure=cause=Internal error while processing REST call to the Configs API.,action=Verify the request and try again.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.resource_path_missing=cause=Resource path missing or wrong.,action=Please reload your artifact in run time.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.io_file_interrupt=cause=IO file system interruption.,action=Please reload your file and make sure it is in the right format.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.unauthorized_request=cause=The request requires user authentication.,action=Please provide the right credentials.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.request_not_found=cause=Request mapping doesn't exist.,action=Please verify your request.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.conflict_adding_resource=cause=Duplicated entry while saving resource.,action=Please make the saving model doesn't exist.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.duplicate_data=cause=Duplicated data - was expecting one result, got more than one.,action=Please provide single resource at a time.
+org.onap.ccsdk.cds.blueprintsprocessor.configs.api.resource_not_found=cause=No response was found for this request in the server.,action=Provide the ID to find the resource.
+
+# Python Executor
+org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor.generic_failure=cause=Internal error in Blueprint Processor run time.,action=Contact CDS administrator team.
+
+# Resource resolution
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.invalid_request_format=cause=bad request provided.,action=Verify the request payload.
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.resource_not_found=cause=No response was found for this resolution in CDS.,action=Verify definition of the resource in CBA. 
+org.onap.ccsdk.cds.blueprintsprocessor.resource.resolution.internal_error=cause=Internal error while processing Resource Resolution.,action=Verify the payload.
+
+org.onap.ccsdk.cds.sdclistener.generic_failure=cause=Internal error in SDC Listener.,action=Contact CDS administrator team.
diff --git a/plans/usecases/pnf-sw-upgrade/cds/resources/importCerAndStartService.sh b/plans/usecases/pnf-sw-upgrade/cds/resources/importCerAndStartService.sh
new file mode 100755 (executable)
index 0000000..c5501d4
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+chmod -R 775 /opt/app/onap/res
+cp -f /opt/app/onap/res/application.properties /opt/app/onap/config
+cp -f /opt/app/onap/res/error-messages_en.properties /opt/app/onap/config
+
+echo "importing aai cert."
+keytool -import -noprompt -trustcacerts -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit -alias aai -import -file /opt/app/onap/res/aai.cert
+
+echo "starting service."
+source /startService.sh
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/sdn/certs/certs.properties b/plans/usecases/pnf-sw-upgrade/sdn/certs/certs.properties
new file mode 100755 (executable)
index 0000000..f8f3fa7
--- /dev/null
@@ -0,0 +1,2 @@
+keys0.zip
+*****
diff --git a/plans/usecases/pnf-sw-upgrade/sdn/certs/keys0.zip b/plans/usecases/pnf-sw-upgrade/sdn/certs/keys0.zip
new file mode 100644 (file)
index 0000000..48b4d90
Binary files /dev/null and b/plans/usecases/pnf-sw-upgrade/sdn/certs/keys0.zip differ
diff --git a/plans/usecases/pnf-sw-upgrade/sdn/docker-compose.yml b/plans/usecases/pnf-sw-upgrade/sdn/docker-compose.yml
new file mode 100755 (executable)
index 0000000..c8a4575
--- /dev/null
@@ -0,0 +1,29 @@
+version: '3'
+
+services:
+  sdnc:
+    image: onap/sdnc-image:latest
+    container_name: sdnc
+    volumes: 
+      - /etc/localtime:/etc/localtime:ro
+      - $SDNC_CERT_PATH:/opt/opendaylight/current/certs
+    entrypoint: ["/opt/onap/sdnc/bin/startODL.sh"]
+    ports:
+      - "8282:8181"
+    hostname:
+      sdnc
+    environment:
+      - MYSQL_ROOT_PASSWORD=password
+      - SDNC_CONFIG_DIR=/opt/onap/sdnc/data/properties
+      - MYSQL_PASSWD=password
+    dns:
+      - ${DNS_IP_ADDR-10.0.100.1}
+    logging:
+      driver:   "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+    extra_hosts:
+      - sdnctldb02:${LOCAL_IP}
+      - sdnctldb01:${LOCAL_IP}
+      - dbhost:${LOCAL_IP}
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/sdn/sdn_setup.sh b/plans/usecases/pnf-sw-upgrade/sdn/sdn_setup.sh
new file mode 100755 (executable)
index 0000000..536777a
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#   Copyright (C) 2020 Nordix Foundation.
+# ================================================================================
+#  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.
+#
+#  SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+# @author Rahul Tyagi (rahul.tyagi@est.tech)
+# setup sdnc
+
+export SDNC_CERT_PATH=${CERT_SUBPATH}
+
+docker pull $NEXUS_DOCKER_REPO/onap/sdnc-image:$SDNC_IMAGE_TAG
+docker tag $NEXUS_DOCKER_REPO/onap/sdnc-image:$SDNC_IMAGE_TAG onap/sdnc-image:latest
+
+#docker pull $NEXUS_DOCKER_REPO/onap/sdnc-ansible-server-image:$SDNC_IMAGE_TAG
+#docker tag $NEXUS_DOCKER_REPO/onap/sdnc-ansible-server-image:$SDNC_IMAGE_TAG onap/sdnc-ansible-server-image:latest
+
+#start SDNC containers with docker compose and configuration from docker-compose.yml
+docker-compose -f $SDNC_DOCKER_PATH/docker-compose.yml -p $PROJECT_NAME up -d
+
+# WAIT 10 minutes maximum and test every 5 seconds if SDNC is up using HealthCheck API
+TIME_OUT=1000
+INTERVAL=30
+TIME=0
+while [ "$TIME" -lt "$TIME_OUT" ]; do
+  response=$(curl --write-out '%{http_code}' --silent --output /dev/null -H "Authorization: Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==" -X POST -H "X-FromAppId: csit-sdnc" -H "X-TransactionId: csit-sdnc" -H "Accept: application/json" -H "Content-Type: application/json" http://localhost:8282/restconf/operations/SLI-API:healthcheck );
+  echo $response
+
+  if [ "$response" == "200" ]; then
+    echo SDNC started in $TIME seconds
+    break;
+  fi
+
+  echo Sleep: $INTERVAL seconds before testing if SDNC is up. Total wait time up now is: $TIME seconds. Timeout is: $TIME_OUT seconds
+  sleep $INTERVAL
+  TIME=$(($TIME+$INTERVAL))
+done
+
+export LOCAL_IP=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')
+sed -i "s/pnfaddr/$LOCAL_IP/g" $REQUEST_DATA_PATH/mount.xml
+
+
+if [ "$TIME" -ge "$TIME_OUT" ]; then
+   echo TIME OUT: karaf session not started in $TIME_OUT seconds... Could cause problems for testing activities...
+fi
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/sdn/sdn_teardown.sh b/plans/usecases/pnf-sw-upgrade/sdn/sdn_teardown.sh
new file mode 100755 (executable)
index 0000000..9f2ac53
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+DOCKER_COMPOSE_FILE_PATH=$SCRIPT_HOME/docker-compose.yml
+
+echo "Tearing down docker containers from remote images ..."
+docker-compose -f $DOCKER_COMPOSE_FILE_PATH -p $PROJECT_NAME down
diff --git a/plans/usecases/pnf-sw-upgrade/setup.sh b/plans/usecases/pnf-sw-upgrade/setup.sh
new file mode 100755 (executable)
index 0000000..95d97ca
--- /dev/null
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#   Copyright (C) 2020 Nordix Foundation.
+# ================================================================================
+#  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.
+#
+#  SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+# @author Rahul Tyagi (rahul.tyagi@est.tech)
+
+
+SCRIPTS="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+export PARENT=usecases
+export SUB_PARENT=pnf-sw-upgrade
+source ${WORKSPACE}/plans/$PARENT/$SUB_PARENT/test.properties
+export $PROJECT_NAME
+export LOCAL_IP=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')
+export MTU=$(/sbin/ifconfig | grep MTU | sed 's/.*MTU://' | sed 's/ .*//' | sort -n | head -1)
+
+if [ "$MTU" == "" ]; then
+         export MTU="1450"
+fi
+unset http_proxy https_proxy
+
+HOST_IP_ADDR=localhost
+
+###################### setup so ##############################
+source $SO_DOCKER_PATH/so_setup.sh
+
+###################### setup sdnc ############################
+source $SDNC_DOCKER_PATH/sdn_setup.sh
+
+###################### setup cds #############################
+source $CDS_DOCKER_PATH/cds_setup.sh
+
+###################### setup pnfsim ##########################
+docker-compose -f $PNF_SIM_DOCKER_PATH/docker-compose.yml -p $PROJECT_NAME up -d 
+
+##### update pnf simulator ip in config deploy request #######
+RES_KEY=$(uuidgen -r)
+sed -i "s/pnfaddr/$LOCAL_IP/g" $REQUEST_DATA_PATH/mount.json
+
+##############################################################
+
+echo "sleeping for 30 sec"
+sleep 30
+
+REPO_IP='127.0.0.1'
+ROBOT_VARIABLES+=" -v REPO_IP:${REPO_IP} "
+ROBOT_VARIABLES+=" -v SCRIPTS:${SCRIPTS} "
+
+
+echo "Finished executing setup for pnf-sw-upgrade"
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/docker-compose.yml b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/docker-compose.yml
new file mode 100755 (executable)
index 0000000..03cad4c
--- /dev/null
@@ -0,0 +1,12 @@
+version: '3'
+
+services:
+  netconf-pnp-simulator:
+    image: nexus3.onap.org:10001/onap/integration/simulators/netconf-pnp-simulator:2.6.1
+    container_name: netconf-simulator
+    restart: always
+    ports:
+      - "830:830"
+      - "6513:6513"
+    volumes:
+      - ./:/config/modules
diff --git a/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/LICENSE b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/LICENSE
new file mode 100755 (executable)
index 0000000..3eface2
--- /dev/null
@@ -0,0 +1,13 @@
+Copyright (C) 2019 Nordix Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/data.xml b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/data.xml
new file mode 100755 (executable)
index 0000000..4f1e7bc
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<software-upgrade xmlns="http://onap.org/pnf-sw-upgrade">
+  <upgrade-package>
+    <id>sw-id-1</id>
+    <current-status>CREATED</current-status>
+    <software-version>test_software_1</software-version>
+    <uri>sftp://127.0.0.1/test_software_1.img</uri>
+    <user>test_user</user>
+    <password>test_password</password>
+    <user-label>trial software update</user-label>
+  </upgrade-package>
+</software-upgrade>
diff --git a/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/model.yang b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/model.yang
new file mode 100755 (executable)
index 0000000..6d41306
--- /dev/null
@@ -0,0 +1,78 @@
+module pnf-sw-upgrade {
+    namespace "http://onap.org/pnf-sw-upgrade";
+    prefix upgrade;
+
+    import ietf-yang-types {
+        prefix yang;
+    }
+
+    revision "2019-12-03" {
+        description
+          "initial version";
+    }
+
+    container software-upgrade {
+        config true;
+        list upgrade-package {
+            key "id";
+            leaf id {
+                type string;
+            }
+            leaf current-status {
+                type enumeration {
+                    enum CREATED;
+                    enum INITIALIZED;
+                    enum DOWNLOAD_IN_PROGRESS;
+                    enum DOWNLOAD_COMPLETED;
+                    enum ACTIVATION_IN_PROGRESS;
+                    enum ACTIVATION_COMPLETED;
+                }
+                description
+                  "List of possible states of the upgrade";
+            }
+            leaf state-change-time {
+                mandatory false;
+                description
+                  "Date and time of the last state change.";
+                type yang:date-and-time;
+            }
+            leaf action {
+                mandatory false;
+                type enumeration {
+                    enum NONE;
+                    enum PRE_CHECK;
+                    enum DOWNLOAD_NE_SW;
+                    enum ACTIVATE_NE_SW;
+                    enum CANCEL;
+                }
+                description
+                  "List of possible actions for the upgrade";
+            }
+            leaf software-version {
+                type string;
+                description
+                  "Possible name or release version of the UP";
+            }
+            leaf uri {
+                type string;
+                description
+                  "A URI that points to the directory where the UP can be found.";
+            }
+            leaf user {
+                type string;
+                description
+                  "Indicates the user.";
+            }
+            leaf password {
+                type string;
+                description
+                  "Indicates the password.";
+            }
+            leaf user-label {
+                type string;
+                description
+                  "Free-text description of the UP.";
+            }
+        }
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/subscriber.py b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/subscriber.py
new file mode 100755 (executable)
index 0000000..810fe45
--- /dev/null
@@ -0,0 +1,212 @@
+#!/usr/bin/env python3
+
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2020 Nordix Foundation.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+__author__ = "Eliezio Oliveira <eliezio.oliveira@est.tech>"
+__copyright__ = "Copyright (C) 2020 Nordix Foundation"
+__license__ = "Apache 2.0"
+
+import time
+from concurrent.futures import ThreadPoolExecutor
+from threading import Timer
+
+import sysrepo as sr
+
+YANG_MODULE_NAME = 'pnf-sw-upgrade'
+
+#
+# ----- BEGIN Finite State Machine definitions -----
+#
+
+# Actions
+ACT_PRE_CHECK = 'PRE_CHECK'
+ACT_DOWNLOAD_NE_SW = 'DOWNLOAD_NE_SW'
+ACT_ACTIVATE_NE_SW = 'ACTIVATE_NE_SW'
+ACT_CANCEL = 'CANCEL'
+
+# States
+ST_CREATED = 'CREATED'
+ST_INITIALIZED = 'INITIALIZED'
+ST_DOWNLOAD_IN_PROGRESS = 'DOWNLOAD_IN_PROGRESS'
+ST_DOWNLOAD_COMPLETED = 'DOWNLOAD_COMPLETED'
+ST_ACTIVATION_IN_PROGRESS = 'ACTIVATION_IN_PROGRESS'
+ST_ACTIVATION_COMPLETED = 'ACTIVATION_COMPLETED'
+
+# Timeout used for timed transitions
+TO_DOWNLOAD = 7
+TO_ACTIVATION = 7
+
+
+def timestamper(sess, key_id):
+    xpath = xpath_of(key_id, 'state-change-time')
+    now = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
+    state = sr.Val(now, sr.SR_STRING_T)
+    sess.set_item(xpath, state)
+
+
+def xpath_of(key_id, leaf_id):
+    selector = "[id='{0}']".format(key_id) if key_id else ''
+    return "/%s:software-upgrade/upgrade-package%s/%s" % (YANG_MODULE_NAME, selector, leaf_id)
+
+
+"""
+The finite state machine (FSM) is represented as a dictionary where the current state is the key, and its value is
+an object (also represented as a dictionary) with the following optional attributes:
+
+- on_enter: a function called when FSM enters this state;
+- transitions: a dictionary mapping every acceptable action to the target state;
+- timed_transition: a pair for a timed transition that will automatically occur after a given interval.
+"""
+STATE_MACHINE = {
+    ST_CREATED: {
+        'transitions': {ACT_PRE_CHECK: ST_INITIALIZED}
+    },
+    ST_INITIALIZED: {
+        'on_enter': timestamper,
+        'transitions': {ACT_DOWNLOAD_NE_SW: ST_DOWNLOAD_IN_PROGRESS}
+    },
+    ST_DOWNLOAD_IN_PROGRESS: {
+        'on_enter': timestamper,
+        'timed_transition': (TO_DOWNLOAD, ST_DOWNLOAD_COMPLETED),
+        'transitions': {ACT_CANCEL: ST_INITIALIZED}
+    },
+    ST_DOWNLOAD_COMPLETED: {
+        'on_enter': timestamper,
+        'transitions': {ACT_ACTIVATE_NE_SW: ST_ACTIVATION_IN_PROGRESS}
+    },
+    ST_ACTIVATION_IN_PROGRESS: {
+        'on_enter': timestamper,
+        'timed_transition': (TO_ACTIVATION, ST_ACTIVATION_COMPLETED),
+        'transitions': {ACT_CANCEL: ST_DOWNLOAD_COMPLETED}
+    },
+    ST_ACTIVATION_COMPLETED: {
+        'on_enter': timestamper,
+        'transitions': {ACT_ACTIVATE_NE_SW: ST_ACTIVATION_IN_PROGRESS}
+    }
+}
+
+#
+# ----- END Finite State Machine definitions -----
+#
+
+
+def main():
+    try:
+        conn = sr.Connection(YANG_MODULE_NAME)
+        sess = sr.Session(conn)
+        subscribe = sr.Subscribe(sess)
+
+        subscribe.module_change_subscribe(YANG_MODULE_NAME, module_change_cb, conn)
+
+        try:
+            print_current_config(sess, YANG_MODULE_NAME)
+        except Exception as e:
+            print(e)
+
+        sr.global_loop()
+
+        print("Application exit requested, exiting.")
+    except Exception as e:
+        print(e)
+
+
+# Function to be called for subscribed client of given session whenever configuration changes.
+def module_change_cb(sess, module_name, event, private_ctx):
+    try:
+        conn = private_ctx
+        change_path = xpath_of(None, 'action')
+        it = sess.get_changes_iter(change_path)
+        while True:
+            change = sess.get_change_next(it)
+            if change is None:
+                break
+            handle_change(conn, change.oper(), change.old_val(), change.new_val())
+    except Exception as e:
+        print(e)
+    return sr.SR_ERR_OK
+
+
+# Function to print current configuration state.
+# It does so by loading all the items of a session and printing them out.
+def print_current_config(session, module_name):
+    select_xpath = f"/{module_name}:*//*"
+
+    values = session.get_items(select_xpath)
+
+    if values is not None:
+        print("========== BEGIN CONFIG ==========")
+        for i in range(values.val_cnt()):
+            print(values.val(i).to_string(), end='')
+        print("=========== END CONFIG ===========")
+
+
+def handle_change(conn, op, old_val, new_val):
+    """
+    Handle individual changes on the model.
+    """
+    if op == sr.SR_OP_CREATED:
+        print("CREATED: %s" % new_val.to_string())
+        xpath = new_val.xpath()
+        last_node = xpath_ctx.last_node(xpath)
+        # Warning: 'key_value' modifies 'xpath'!
+        key_id = xpath_ctx.key_value(xpath, 'upgrade-package', 'id')
+        if key_id and last_node == 'action':
+            executor.submit(execute_action, conn, key_id, new_val.data().get_enum())
+    elif op == sr.SR_OP_DELETED:
+        print("DELETED: %s" % old_val.to_string())
+    elif op == sr.SR_OP_MODIFIED:
+        print("MODIFIED: %s to %s" % (old_val.to_string(), new_val.to_string()))
+    elif op == sr.SR_OP_MOVED:
+        print("MOVED: %s after %s" % (new_val.xpath(), old_val.xpath()))
+
+
+def execute_action(conn, key_id, action):
+    sess = sr.Session(conn)
+    try:
+        cur_state = sess.get_item(xpath_of(key_id, 'current-status')).data().get_enum()
+        next_state_str = STATE_MACHINE[cur_state]['transitions'].get(action, None)
+        if next_state_str:
+            handle_set_state(conn, key_id, next_state_str)
+        sess.delete_item(xpath_of(key_id, 'action'))
+        sess.commit()
+    finally:
+        sess.session_stop()
+
+
+def handle_set_state(conn, key_id, state_str):
+    sess = sr.Session(conn)
+    try:
+        state = sr.Val(state_str, sr.SR_ENUM_T)
+        sess.set_item(xpath_of(key_id, 'current-status'), state)
+        on_enter = STATE_MACHINE[state_str].get('on_enter', None)
+        if on_enter:
+            # noinspection PyCallingNonCallable
+            on_enter(sess, key_id)
+        sess.commit()
+        delay, next_state_str = STATE_MACHINE[state_str].get('timed_transition', [0, None])
+        if delay:
+            Timer(delay, handle_set_state, (conn, key_id, next_state_str)).start()
+    finally:
+        sess.session_stop()
+
+
+if __name__ == '__main__':
+    xpath_ctx = sr.Xpath_Ctx()
+    executor = ThreadPoolExecutor(max_workers=2)
+    main()
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/cloud-esr-system-info.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/cloud-esr-system-info.json
new file mode 100755 (executable)
index 0000000..1a16538
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "esr-system-info-id": "e6a0b318-9756-4f11-94e8-919312d6c2bd",
+    "system-name": "csit cloud vim",
+    "type": "OPENSTACK",
+    "vendor": "RedHat",
+    "version": "1",
+    "service-url": "https://csit.PnfSwUcloud.com:5000/v3/",
+    "user-name": "",
+    "password": "",
+    "system-type": "VIM",
+    "port": "example-port-val-93234",
+    "cloud-domain": "CCP_Domain_34466",
+    "default-tenant": "693c7729b2364a26a3ca602e6f66187d"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/cloud-region.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/cloud-region.json
new file mode 100755 (executable)
index 0000000..fa32840
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "cloud-owner": "CloudOwner",
+    "cloud-region-id": "PnfSwUCloudRegion",
+    "cloud-type": "openstack",
+    "owner-defined-type": "OwnerType",
+    "cloud-region-version": "1.0",
+    "cloud-zone": "CloudZone",
+    "complex-name": "clli1",
+    "cloud-extra-info": ""
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/customer.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/customer.json
new file mode 100755 (executable)
index 0000000..6c53c05
--- /dev/null
@@ -0,0 +1,73 @@
+{
+    "global-customer-id": "DemoCustomer",
+    "subscriber-name": "DemoCustomer",
+    "subscriber-type": "INFRA",
+    "service-subscriptions": {
+        "service-subscription": [
+            {
+                "service-type": "vLB",
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "tenant",
+                            "relationship-label": "org.onap.relationships.inventory.Uses",
+                            "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/xyzcloud/tenants/tenant/693c7729b2364a26a3ca602e6f66187d",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "cloud-region.cloud-owner",
+                                    "relationship-value": "CloudOwner"
+                                },
+                                {
+                                    "relationship-key": "cloud-region.cloud-region-id",
+                                    "relationship-value": "xyzcloud"
+                                },
+                                {
+                                    "relationship-key": "tenant.tenant-id",
+                                    "relationship-value": "693c7729b2364a26a3ca602e6f66187d"
+                                }
+                            ],
+                            "related-to-property": [
+                                {
+                                    "property-key": "tenant.tenant-name",
+                                    "property-value": "admin"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            },
+            {
+                "service-type": "vCPE",
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "tenant",
+                            "relationship-label": "org.onap.relationships.inventory.Uses",
+                            "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/xyzcloud/tenants/tenant/693c7729b2364a26a3ca602e6f66187d",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "cloud-region.cloud-owner",
+                                    "relationship-value": "CloudOwner"
+                                },
+                                {
+                                    "relationship-key": "cloud-region.cloud-region-id",
+                                    "relationship-value": "xyzcloud"
+                                },
+                                {
+                                    "relationship-key": "tenant.tenant-id",
+                                    "relationship-value": "693c7729b2364a26a3ca602e6f66187d"
+                                }
+                            ],
+                            "related-to-property": [
+                                {
+                                    "property-key": "tenant.tenant-name",
+                                    "property-value": "admin"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            }
+        ]
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/esr-system-info.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/esr-system-info.json
new file mode 100755 (executable)
index 0000000..d204a77
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "esr-system-info-id": "5c067098-f2e3-40f7-a7ba-155e7c61e916",
+    "system-name": "vnfmSimulator",
+    "type": "simulator",
+    "vendor": "EST",
+    "version": "V1.0",
+    "service-url": "https://so-vnfm-simulator:9093/vnflcm/v1",
+    "user-name": "",
+    "password": "",
+    "system-type": "VNFM"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/esr-vnfm.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/esr-vnfm.json
new file mode 100755 (executable)
index 0000000..4d23b43
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "vnfm-id": "c5e99cee-1996-4606-b697-838d51d4e1a3",
+    "vim-id": "PnfSwUCsitVimId",
+    "certificate-url": ""
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/line-of-business.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/line-of-business.json
new file mode 100755 (executable)
index 0000000..69f872b
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "line-of-business-name": "PnfSwUCsitLineOfBusiness"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/owning-entity.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/owning-entity.json
new file mode 100755 (executable)
index 0000000..3bfd9cc
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "owning-entity-id": "f2e1071e-3d47-4a65-94d4-e473ec03326a",
+    "owning-entity-name": "OE-Demonstration"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/platform.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/platform.json
new file mode 100755 (executable)
index 0000000..3265a06
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "platform-name": "PnfSwUCsitPlatform"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/pnf.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/pnf.json
new file mode 100755 (executable)
index 0000000..ab39d8c
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "pnf-name2":"PNFDemo-pnf-name2-val-78244",
+  "pnf-name2-source":"PNFDemo-pnf-name2-source-val-99275",
+  "equip-type":"PNFDemo-equip-type-val-20348",
+  "equip-vendor":"PNFDemo-equip-vendor-val-52182",
+  "equip-model":"PNFDemo-equip-model-val-8370",
+  "management-option":"PNFDemo-management-option-val-72881",
+  "ipaddress-v4-oam":"pnfaddr",
+  "ipaddress-v6-oam":"0:0:0:0:0:0",
+  "sw-version":"pnf_sw_version-1.0.0",
+  "pnf-name":"PNFDemo",
+  "pnf-id":"PNFDemo",
+  "in-maint":false,
+  "resource-version":"1570117118905",
+  "selflink": "http://localhost:9993/pnf/PNFDemo"
+}
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/project.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/project.json
new file mode 100755 (executable)
index 0000000..f67dbc1
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "project-name": "PnfSwUCsitProject"
+}
+
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/tenant.json b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/tenant.json
new file mode 100755 (executable)
index 0000000..746131a
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "tenant-id": "693c7729b2364a26a3ca602e6f66187d",
+    "tenant-name": "admin"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/apply-workarounds.sh b/plans/usecases/pnf-sw-upgrade/so/config/apply-workarounds.sh
new file mode 100755 (executable)
index 0000000..5833a9e
--- /dev/null
@@ -0,0 +1,111 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 Nordix Foundation.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# @author Waqas Ikram (waqas.ikram@est.tech)
+
+WORKFLOW_TABLE_NAME="workflow"
+TABLE_EXISTS_QUERY="select count(*) from information_schema.tables WHERE table_schema='$CATALOG_DB' AND table_name='$WORKFLOW_TABLE_NAME';"
+SLEEP_TIME=5
+FLY_WAY_MIGRATION_QUERY="SELECT COUNT(*) FROM flyway_schema_history WHERE script LIKE '%R__MacroData%' AND installed_on IS NOT NULL;"
+TIME_OUT_DEFAULT_VALUE_SEC=1200 #20 mins
+SCRIPT_NAME=$(basename $0)
+
+current_timestamp()
+{
+ date +"%Y-%m-%d %H:%M:%S"
+}
+
+wait_for_database_availability()
+{
+ echo "$SCRIPT_NAME $(current_timestamp): Checking for database availability"
+ until echo '\q' | mysql -h $DB_HOST -P $DB_PORT -uroot -p$MYSQL_ROOT_PASSWORD $CATALOG_DB; do
+     >&2 echo "$SCRIPT_NAME $(current_timestamp): Database is unavailable - sleeping for ${SLEEP_TIME} seconds"
+     isTimeOut
+     sleep ${SLEEP_TIME}
+ done
+
+ echo "$SCRIPT_NAME $(current_timestamp): Database is available now"
+}
+
+wait_container_to_create_table()
+{
+ while [ $(mysql -h $DB_HOST -P $DB_PORT -uroot -p$MYSQL_ROOT_PASSWORD $CATALOG_DB -sse "$TABLE_EXISTS_QUERY") -eq "0" ] ; do
+     echo "$SCRIPT_NAME $(current_timestamp): Waiting for so-catalog container to create tables - sleeping for ${SLEEP_TIME} seconds"
+     isTimeOut
+     sleep ${SLEEP_TIME}
+ done
+ sleep 5s
+ echo "$SCRIPT_NAME $(current_timestamp): $CATALOG_DB tables available now . . ."
+}
+
+apply_workaround()
+{
+ echo "$SCRIPT_NAME $(current_timestamp): Applying workaround . . ."
+
+ wait_for_database_availability
+ wait_container_to_create_table
+ echo "$SCRIPT_NAME $(current_timestamp): Will insert data into $CATALOG_DB"
+ mysql -h $DB_HOST -uroot -p$MYSQL_ROOT_PASSWORD $CATALOG_DB << EOF
+ BEGIN;
+  
+  insert into $WORKFLOW_TABLE_NAME(artifact_uuid, artifact_name, name, operation_name, version, description, body, resource_target, source) values
+  ('4752c287-c5a8-40a6-8fce-077e1d54104b','PNFSoftwareUpgrade','PNFSoftwareUpgrade','PNFSoftwareUpgrade',1.0,'Pnf Workflow to upgrade software',null,'pnf','native');
+
+  insert into $WORKFLOW_TABLE_NAME(artifact_uuid, artifact_name, name, operation_name, version, description, body, resource_target, source) values
+  ('02bffbd9-6af0-4f8d-bf9b-d1dfccd28c84','PNFSWUPDownload','PNFSWUPDownload','PNFSWUPDownload',1.0,'Pnf Workflow to download software',null,'pnf','native');
+
+ COMMIT;
+EOF
+
+ if [ $? -ne 0 ]; then
+    echo "$SCRIPT_NAME $(current_timestamp): Failed to execute workaround . . ."
+    exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): Finished applying workaround . . ."
+}
+
+isTimeOut()
+{
+ if [ `date +%s` -gt $TIME_OUT_END_TIME_IN_SECONDS ]; then
+    echo "$SCRIPT_NAME $(current_timestamp): workaround script timed out . . ."
+    exit 1;
+ fi
+}
+
+# main body
+if [ -z "$TIME_OUT_IN_SECONDS"]; then
+    echo "$SCRIPT_NAME $(current_timestamp): TIME_OUT_IN_SECONDS attribute is empty will use default val: $TIME_OUT_DEFAULT_VALUE_SEC"
+    TIME_OUT_IN_SECONDS=$TIME_OUT_DEFAULT_VALUE_SEC
+fi
+
+DIGITS_REGEX='^[0-9]+$'
+if ! [[ $TIME_OUT_IN_SECONDS =~ $DIGIT_REGEX ]] ; then
+    echo "$SCRIPT_NAME $(current_timestamp): TIME_OUT_IN_SECONDS attribute Must be number: $TIME_OUT_IN_SECONDS, will use default val: $TIME_OUT_DEFAULT_VALUE_SEC"
+    TIME_OUT_IN_SECONDS=$TIME_OUT_DEFAULT_VALUE_SEC
+fi
+
+START_TIME_IN_SECONDS=`date +%s`
+TIME_OUT_END_TIME_IN_SECONDS=$(($START_TIME_IN_SECONDS+$TIME_OUT_IN_SECONDS));
+echo "$SCRIPT_NAME $(current_timestamp): Workaround script will time out at `date -d @$TIME_OUT_END_TIME_IN_SECONDS`"
+
+apply_workaround
+
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/certificates/aai-certificate/aai.cert b/plans/usecases/pnf-sw-upgrade/so/config/certificates/aai-certificate/aai.cert
new file mode 100755 (executable)
index 0000000..9acb8bb
--- /dev/null
@@ -0,0 +1,31 @@
+Bag Attributes
+    friendlyName: so@so.onap.org
+    localKeyID: 54 69 6D 65 20 31 35 36 34 30 35 32 33 31 34 37 38 34 
+subject=CN = aai-simulator, emailAddress = , OU = so@so.onap.org, OU = OSAAF, O = ONAP, C = US
+
+issuer=C = US, O = ONAP, OU = OSAAF, CN = intermediateCA_9
+
+-----BEGIN CERTIFICATE-----
+MIIEBzCCAu+gAwIBAgIIdC1kel7DdnYwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UE
+BhMCVVMxDTALBgNVBAoMBE9OQVAxDjAMBgNVBAsMBU9TQUFGMRkwFwYDVQQDDBBp
+bnRlcm1lZGlhdGVDQV85MB4XDTE5MDcyNTEwNTgzNFoXDTIwMDcyNTEwNTgzNFow
+bjEWMBQGA1UEAwwNYWFpLXNpbXVsYXRvcjEPMA0GCSqGSIb3DQEJARYAMRcwFQYD
+VQQLDA5zb0Bzby5vbmFwLm9yZzEOMAwGA1UECwwFT1NBQUYxDTALBgNVBAoMBE9O
+QVAxCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+185xCE6cmsY6XB5Dd/5GlfuWjN05KKk3akymxhbJLa9ektlusmuTPt4cnxD+e4b6
+dymqHzQ6C206TBK1jaDzcF07Ag7VTpxmlgaSukQ+aZoXfIcs80lWCLnNvC2MrOuh
+9uhUILAmuddo01cIHJvti5R2g6BEirCGsVKBSwmXRotxHyzUg9IwOpeGy0G1ZDjU
+OiMqY5qOonVTEz1AganctdiWK1/eZ5IBD7gQwckS5n1a6RYMVSnr1vKLoiZq76Bp
+wKy3EBX16jlmQMC5Aj9/GDezJg0bPvlikL3VUsC76DRShucsxS3SzVxeAJ5nsH8S
+qUElpbe3uabhFG2qKmtvdwIDAQABo4HPMIHMMAkGA1UdEwQCMAAwDgYDVR0PAQH/
+BAQDAgXgMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBUBgNVHSME
+TTBLgBSB95lbELnIjN7zUl7qTmmgQz6s3aEwpC4wLDEOMAwGA1UECwwFT1NBQUYx
+DTALBgNVBAoMBE9OQVAxCzAJBgNVBAYTAlVTggEHMB0GA1UdDgQWBBSQ54p+SID0
+2p21lUHY9YC1ZZfkZTAYBgNVHREEETAPgg1hYWktc2ltdWxhdG9yMA0GCSqGSIb3
+DQEBCwUAA4IBAQBRGK6Iyjc/0bC3+qjPuNwSlu1pUcgHtgxP/oTU5f9xMSkSjIP0
+weVnIEGOwlW8GRbDPQza14AHETTxJ17rv6p6h7l/dZZmbMPl2S+QXGptgDWR6zY7
+q5ROecGcQzgto6lTMcKgBMW+ct3Tb3khMqP6ewzGz85SY7BgyVE7HFG9M5BM3NhX
+ovAcj93C24DFKLDKxHrrsVIROlFk6QW2+kb0zo1YzVc6NNJY2ViXBrM5zrG21tDj
+VEv0JaHKPYhzWCb7ZcSSo/ftZ2yDsRGS8r6DK5sYCfLifloMVJhF04hOC+ZbxiiB
+JgYniQPmb0Zj5BfXWovdAe/89wr5aokQ3GZL
+-----END CERTIFICATE-----
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/distribution-test-zip/zipped_sdc_csar.tar.gz b/plans/usecases/pnf-sw-upgrade/so/config/distribution-test-zip/zipped_sdc_csar.tar.gz
new file mode 100644 (file)
index 0000000..5af091b
Binary files /dev/null and b/plans/usecases/pnf-sw-upgrade/so/config/distribution-test-zip/zipped_sdc_csar.tar.gz differ
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/env b/plans/usecases/pnf-sw-upgrade/so/config/env
new file mode 100644 (file)
index 0000000..77e3dbf
--- /dev/null
@@ -0,0 +1,6 @@
+NEXUS_DOCKER_REPO_MSO=nexus3.onap.org:10001
+DOCKER_ENVIRONMENT=remote
+TAG=1.6.0-STAGING-latest
+TIME_OUT_DEFAULT_VALUE_SEC=1200
+PROJECT_NAME=pnfSwU
+DEFAULT_NETWORK_NAME=pnfswu_default
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/override-files/api-handler-infra/onapheat/override.yaml b/plans/usecases/pnf-sw-upgrade/so/config/override-files/api-handler-infra/onapheat/override.yaml
new file mode 100755 (executable)
index 0000000..10a3ec2
--- /dev/null
@@ -0,0 +1,133 @@
+server:
+    port: 8080
+    tomcat:
+        max-threads: 50
+ssl-enable: false
+
+mso:
+  msoKey: 07a7159d3bf51a0e53be7a8f89699be7
+  logPath: logs
+  site-name: onapheat
+  adapters:
+    requestDb:
+      endpoint: http://request-db-adapter:8083
+      auth: Basic YnBlbDpwYXNzd29yZDEk
+  catalog:
+    db:
+      spring:
+        endpoint: http://catalog-db-adapter:8082
+  db:
+    auth: Basic YnBlbDpwYXNzd29yZDEk
+  config:
+    path: /src/main/resources/
+  infra:
+    default:
+      alacarte:
+        orchestrationUri: /mso/async/services/ALaCarteOrchestrator
+        recipeTimeout: 180
+        testApi: VNF_API
+      service:
+        macro:
+          default:
+            testApi: GR_API
+  camundaURL: http://bpmn-infra:8081
+  camundaAuth: AE2E9BE6EF9249085AF98689C4EE087736A5500629A72F35068FFB88813A023581DD6E765071F1C04075B36EA4213A
+  async:
+    core-pool-size: 50
+    max-pool-size: 50
+    queue-capacity: 500
+  sdc:
+    client:
+      auth: F3473596C526938329DF877495B494DC374D1C4198ED3AD305EA3ADCBBDA1862
+    activate:
+      instanceid: test
+      userid: cs0008
+    endpoint: http://c1.vm1.mso.simpledemo.onap.org:28090
+  tenant:
+    isolation:
+      retry:
+        count: 3
+  aai:
+    endpoint: https://aai-simulator:9993
+    auth: 2630606608347B7124C244AB0FE34F6F
+  extApi:
+    endpoint: http://nbi.onap:8080/nbi/api/v3
+  so:
+    operational-environment:
+      dmaap:
+        username: testuser
+        password: VjR5NDcxSzA=
+        host: http://c1.vm1.mso.simpledemo.onap.org:28090
+        auth: 51EA5414022D7BE536E7516C4D1A6361416921849B72C0D6FC1C7F262FD9F2BBC2AD124190A332D9845A188AD80955567A4F975C84C221EEA8243BFD92FFE6896CDD1EA16ADD34E1E3D47D4A
+      publisher:
+        topic: com.att.ecomp.mso.operationalEnvironmentEvent
+  health:
+    auth: Basic bXNvX2FkbWlufHBhc3N3b3JkMSQ=
+    endpoints:
+      - subsystem: apih
+        uri: http://bpmn-infra:8081
+      - subsystem: catalogdb
+        uri: http://catalog-db-adapter:8082
+
+spring:
+  datasource:
+    hikari:
+      jdbcUrl: jdbc:mariadb://mariadb:3306/catalogdb
+      username: cataloguser
+      password: catalog123
+      driver-class-name: org.mariadb.jdbc.Driver
+      pool-name: catdb-pool
+      registerMbeans: true
+  jpa:
+      show-sql: true
+      hibernate:
+        dialect: org.hibernate.dialect.MySQL5Dialect
+        ddl-auto: validate
+        naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
+        enable-lazy-load-no-trans: true
+  jersey:
+    type: filter
+
+  security:
+    usercredentials:
+    -
+      username: sitecontrol
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: SiteControl-Client
+    -
+      username: gui
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: GUI-Client
+    -
+      username: infraportal
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: InfraPortal-Client
+    -
+      username: InfraPortalClient
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: InfraPortal-Client
+    -
+      username: bpel
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: BPEL-Client
+    -
+      username: mso_admin
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: ACTUATOR
+
+request:
+  datasource:
+    hikari:
+      jdbcUrl: jdbc:mariadb://mariadb:3306/requestdb
+      username: requestuser
+      password: request123
+      driver-class-name: org.mariadb.jdbc.Driver
+      pool-name: reqdb-pool
+      registerMbeans: true
+org:
+  onap:
+    so:
+      cloud-owner: CloudOwner
+      adapters:
+        network:
+          encryptionKey: 07a7159d3bf51a0e53be7a8f89699be7
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/override-files/bpmn-infra/onapheat/override.yaml b/plans/usecases/pnf-sw-upgrade/so/config/override-files/bpmn-infra/onapheat/override.yaml
new file mode 100755 (executable)
index 0000000..4dd959a
--- /dev/null
@@ -0,0 +1,337 @@
+aai:
+  auth:  221187EFA3AD4E33600DE0488F287099934CE65C3D0697BCECC00BB58E784E07CD74A24581DC31DBC086FF63DF116378776E9BE3D1325885
+  dme2:
+    timeout: '30000'
+  endpoint: https://aai-simulator:9993
+  workflowAaiDistributionDelay: PT30S
+  pnfEntryNotificationTimeout: P14D
+camunda:
+  bpm:
+    admin-user:
+      id: admin
+      password: so_Admin123
+    history-level: full
+    job-execution:
+      max-pool-size: 30
+      core-pool-size: 3
+cds:
+    endpoint: blueprints-processor
+    port: 9111
+    auth: Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==
+    timeout: 60
+entitymanager:
+  packagesToScan: com
+pnf:
+  dmaap:
+    host: message-router
+    port: 3904
+    protocol: http
+    uriPathPrefix: events
+    topicName: pnfReady
+    consumerGroup: consumerGroup
+    consumerId: consumerId
+    topicListenerDelayInSeconds: 5
+mso:
+  msoKey: 07a7159d3bf51a0e53be7a8f89699be7
+  config:
+    path: /var/csar/
+  correlation:
+    timeout: 60
+  logPath: logs
+  async:
+    core-pool-size: 50
+    max-pool-size: 50
+    queue-capacity: 500
+  aai:
+    endpoint: https://aai-simulator:9993
+  adapters:
+    completemsoprocess:
+      endpoint:  http://bpmn-infra:8081/CompleteMsoProcess
+    requestDb:
+      endpoint: http://request-db-adapter:8083
+      auth: Basic YnBlbDpwYXNzd29yZDEk
+    db:
+      auth: 33293332AEC4930F655D8E2E8BB08937
+      password: wLg4sjrAFUS8rfVfdvTXeQ==
+      endpoint: http://c1.vm1.mso.simpledemo.onap.org:8083/services/RequestsDbAdapter
+      spring:
+        endpoint: http://c1.vm1.mso.simpledemo.onap.org:8083
+    network:
+      endpoint: http://c1.vm1.mso.simpledemo.onap.org:8087/services/NetworkAdapter
+      rest:
+        endpoint: http://c1.vm1.mso.simpledemo.onap.org:8087/services/rest/v1/networks
+    openecomp:
+      db:
+        endpoint: http://c1.vm1.mso.simpledemo.onap.org:8083/services/RequestsDbAdapter
+    po:
+      auth: 33293332AEC4930F655D8E2E8BB08937
+      password: B8EBDE0311F0AF355CF3F2FD505A8CAD
+    sdnc:
+      endpoint: http://c1.vm1.mso.simpledemo.onap.org:8086/adapters/SDNCAdapter
+      rest:
+        endpoint: http://c1.vm1.mso.simpledemo.onap.org:8086/adapters/rest/v1/sdnc
+      timeout: PT60M
+    tenant:
+      endpoint: http://c1.vm1.mso.simpledemo.onap.org:8087/services/TenantAdapter
+    vnf:
+      endpoint: http://c1.vm1.mso.simpledemo.onap.org:8087/services/VnfAdapter
+      rest:
+        endpoint: http://c1.vm1.mso.simpledemo.onap.org:8087/services/rest/v1/vnfs
+    volume-groups:
+      rest:
+        endpoint: http://c1.vm1.mso.simpledemo.onap.org:8087/services/rest/v1/volume-groups
+    vnf-async:
+      endpoint: http://c1.vm1.mso.simpledemo.onap.org:8087/services/VnfAdapterAsync
+  bpmn:
+    process:
+      historyTimeToLive: '30'
+  callbackRetryAttempts: '5'
+  catalog:
+    db:
+      endpoint: http://catalog-db-adapter:8082/ecomp/mso/catalog
+      spring:
+        endpoint: http://catalog-db-adapter:8082
+  db:
+    auth: Basic YnBlbDpwYXNzd29yZDEk
+  default:
+    adapter:
+      namespace: http://org.onap.mso
+  healthcheck:
+    log:
+      debug: 'false'
+  infra:
+    customer:
+      id: testCustIdInfra
+  po:
+    timeout: PT60M
+  request:
+    db:
+      endpoint: http://c1.vm1.mso.simpledemo.onap.org:8083/
+  rollback: 'true'
+  sdnc:
+    password: 3141634BF7E070AA289CF2892C986C0B
+  service:
+    agnostic:
+      sniro:
+        endpoint: /sniro/api/v2/placement
+        host: http://c1.vm1.mso.simpledemo.onap.org:30253
+  site-name: CamundaEngine
+  sniro:
+    auth: test:testpwd
+    callback: http://c1.vm1.mso.simpledemo.onap.org:8086/adapters/rest/SDNCNotify
+    endpoint: http://replaceme:28090/optimizationInstance/V1/create
+    timeout: PT30M
+  oof:
+    auth: test:testpwd
+    callbackEndpoint: http://bpmn-infra:8081/mso/WorkflowMessage
+    endpoint: http://oof.api.simpledemo.openecomp.org:8698/api/oof/v1/placement
+    timeout: PT30M
+  workflow:
+    CreateGenericVNFV1:
+      aai:
+        volume-group:
+          uri: /aai/v6/cloud-infrastructure/volume-groups/volume-group
+    default:
+      aai:
+        version: '14'
+        cloud-region:
+          version: '14'
+        generic-vnf:
+          version: '14'
+        v14:
+          customer:
+            uri: /aai/v14/business/customers/customer
+          generic-query:
+            uri: /aai/v14/search/generic-query
+          generic-vnf:
+            uri: /aai/v14/network/generic-vnfs/generic-vnf
+          l3-network:
+            uri: /aai/v14/network/l3-networks/l3-network
+          network-policy:
+            uri: /aai/v14/network/network-policies/network-policy
+          nodes-query:
+            uri: /aai/v14/search/nodes-query
+          route-table-reference:
+            uri: /aai/v14/network/route-table-references/route-table-reference
+          tenant:
+            uri: /aai/v14/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/RegionOne/tenants/tenant
+          vce:
+            uri: /aai/v14/network/vces/vce
+          vpn-binding:
+            uri: /aai/v14/network/vpn-bindings/vpn-binding
+          sp-partner:
+            uri: /aai/v14/business/sp-partners/sp-partner
+          device:
+            uri: /aai/v14/network/devices/device
+        v11:
+          customer:
+            uri: /aai/v11/business/customers/customer
+          generic-query:
+            uri: /aai/v11/search/generic-query
+          generic-vnf:
+            uri: /aai/v11/network/generic-vnfs/generic-vnf
+          l3-network:
+            uri: /aai/v11/network/l3-networks/l3-network
+          network-policy:
+            uri: /aai/v11/network/network-policies/network-policy
+          nodes-query:
+            uri: /aai/v11/search/nodes-query
+          route-table-reference:
+            uri: /aai/v11/network/route-table-references/route-table-reference
+          tenant:
+            uri: /aai/v11/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/RegionOne/tenants/tenant
+          vce:
+            uri: /aai/v11/network/vces/vce
+          vpn-binding:
+            uri: /aai/v11/network/vpn-bindings/vpn-binding
+        v8:
+          configuration:
+            uri: /aai/v11/network/configurations/configuration
+          customer:
+            uri: /aai/v8/business/customers/customer
+          generic-query:
+            uri: /aai/v8/search/generic-query
+          l3-network:
+            uri: /aai/v8/network/l3-networks/l3-network
+          network-policy:
+            uri: /aai/v8/network/network-policies/network-policy
+          nodes-query:
+            uri: /aai/v8/search/nodes-query
+          route-table-reference:
+            uri: /aai/v8/network/route-table-references/route-table-reference
+          tenant:
+            uri: /aai/v8/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/RegionOne/tenants/tenant
+          vce:
+            uri: /aai/v8/network/vces/vce
+          vpn-binding:
+            uri: /aai/v8/network/vpn-bindings/vpn-binding
+        v9:
+          cloud-region:
+            uri: /aai/v9/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner
+          generic-vnf:
+            uri: /aai/v9/network/generic-vnfs/generic-vnf
+      retry:
+        attempts: '1'
+    deleteCinderVolumeV1:
+      aai:
+        volume-group:
+          uri: /aai/v6/cloud-infrastructure/volume-groups/volume-group
+    global:
+      default:
+        aai:
+          namespace: http://org.onap.aai.inventory/
+          version: 14
+    message:
+      endpoint: http://bpmn-infra:8081/mso/WorkflowMessage
+    notification:
+      name: GenericNotificationServiceATT
+    sdncadapter:
+      callback: http://bpmn-infra:8081/mso/SDNCAdapterCallbackService
+    vnfadapter:
+      create:
+        callback: http://c1.vm1.mso.simpledemo.onap.org:8087/mso/vnfAdapterNotify
+      delete:
+        callback: http://c1.vm1.mso.simpledemo.onap.org:8087/mso/vnfAdapterNotify
+      query:
+        callback: http://c1.vm1.mso.simpledemo.onap.org:8087/mso/vnfAdapterNotify
+      rollback:
+        callback: http://c1.vm1.mso.simpledemo.onap.org:8087/mso/vnfAdapterNotify
+  global:
+    dmaap:
+      username: testuser
+      password: alRyMzJ3NUNeakxl
+      host: http://10.42.111.36:904
+      auth: A4DE725B8B0D1A745049409B16762C16BC9B48555DC157272741D616323104442B3AAC052ED17E74EECA136B89C8C6615C8CC269ED5834EC47C6BE6A75DF39C6C07B07DF064CE268BE6510F472
+      publisher:
+        topic: replaceme
+policy:
+  auth: Basic dGVzdHBkcDphbHBoYTEyMw==
+  client:
+    auth: Basic bTAzNzQzOnBvbGljeVIwY2sk
+  endpoint: https://localhost:8081/pdp/api/
+  environment: TEST
+sdnc:
+  auth: Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==
+  host: http://sdnc:8282
+  path: /restconf/operations/GENERIC-RESOURCE-API
+  si:
+    svc:
+      types: PORT-MIRROR,PPROBE
+
+so:
+  vnfm:
+    adapter:
+      url: https://so-vnfm-adapter:9092/so/vnfm-adapter/v1/
+      auth: Basic dm5mbTpwYXNzd29yZDEk
+
+appc:
+  client:
+    topic:
+      read:
+        name: APPC-LCM-WRITE
+        timeout: 360000
+      write: APPC-LCM-READ
+      sdnc:
+        read:
+          name: SDNC-LCM-WRITE
+        write: SDNC-LCM-READ
+    response:
+      timeout: 360000
+    key: VIlbtVl6YLhNUrtU
+    secret: 64AG2hF4pYeG2pq7CT6XwUOT
+    service: ueb
+    poolMembers: ueb1.simpledemo.onap.org:3904,ueb2.simpledemo.onap.org:3904
+server:
+  port: 8081
+  tomcat:
+    max-threads: 50
+spring:
+  datasource:
+     driver-class-name: org.mariadb.jdbc.Driver
+     url: jdbc:mariadb://mariadb:3306/camundabpmn
+     username: camundauser
+     password: camunda123
+     dbcp2:
+      initial-size: 5
+      max-total: 20
+      validation-query: select 1
+      test-on-borrow: true
+  security:
+    usercredentials:
+    -
+      username: apihBpmn
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: BPMN-Client
+    -
+      username: sdncaBpmn
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: BPMN-Client
+    -
+      username: poBpmn
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: BPMN-Client
+    -
+      username: wmaBpmn
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: BPMN-Client
+    -
+      username: sniro
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: SNIRO-Client
+    -
+      username: mso_admin
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: ACTUATOR
+org:
+  onap:
+    so:
+      cloud-owner: CloudOwner
+rest:
+  http:
+    client:
+      configuration:
+        ssl:
+          keyStore: classpath:org.onap.so.p12
+          keyStorePassword: 'RLe5ExMWW;Kd6GTSt0WQz;.Y'
+          trustStore: classpath:org.onap.so.trust.jks
+          trustStorePassword: '6V%8oSU$,%WbYp3IUe;^mWt4'
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/override-files/catalog-db-adapter/onapheat/override.yaml b/plans/usecases/pnf-sw-upgrade/so/config/override-files/catalog-db-adapter/onapheat/override.yaml
new file mode 100755 (executable)
index 0000000..8ab9615
--- /dev/null
@@ -0,0 +1,69 @@
+server:
+    port: 8082
+    tomcat:
+        max-threads: 50
+ssl-enable: false
+mso:
+  logPath: logs
+  site-name: onapheat
+  catalog:
+    db:
+      spring:
+        endpoint: http://catalog-db-adapter:8082
+  db:
+    auth: Basic YnBlbDpwYXNzd29yZDEk
+spring:
+  datasource:
+    hikari:
+      jdbcUrl: jdbc:mariadb://${DB_HOST}:${DB_PORT}/catalogdb
+      username: cataloguser
+      password: catalog123
+      driver-class-name: org.mariadb.jdbc.Driver
+      pool-name: catdb-pool
+      registerMbeans: true
+  jpa:
+    generate-ddl: false
+    show-sql: false
+    hibernate:
+      ddl-auto: validate
+      naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
+      enable-lazy-load-no-trans: true
+    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+  security:
+    usercredentials:
+    -
+      username: bpel
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: BPEL-Client
+    -
+      username: mso_admin
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: ACTUATOR
+
+#Actuator
+management:
+  context-path: /manage
+
+flyway:
+  baseline-on-migrate: true
+  url: jdbc:mariadb://${DB_HOST}:${DB_PORT}/catalogdb
+  user: cataloguser
+  password: catalog123
+  
+cloud_config:
+  identity_services:
+    DEFAULT_KEYSTONE:
+      identity_url: http://192.168.35.52:5000/v2.0
+      mso_id: admin
+      mso_pass: admin
+      admin_tenant: service
+      member_role: admin
+      tenant_metadata: true
+      identity_server_type: KEYSTONE
+      identity_authentication_type: USERNAME_PASSWORD
+      project_domain_name: service
+      user_domain_name: admin
+  cloud_sites:
+    RegionOne:
+      region_id: RegionOne
+      clli: RegionOne 
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/override-files/request-db-adapter/onapheat/override.yaml b/plans/usecases/pnf-sw-upgrade/so/config/override-files/request-db-adapter/onapheat/override.yaml
new file mode 100755 (executable)
index 0000000..6586116
--- /dev/null
@@ -0,0 +1,51 @@
+# will be used as entry in DB to say SITE OFF/ON for healthcheck
+
+server:
+    port: 8083
+    tomcat:
+        max-threads: 50
+ssl-enable: false
+mso:
+  logPath: logs
+  site-name: localSite
+  adapters:
+    requestDb:
+      endpoint: http://request-db-adapter:8083
+      auth: Basic YnBlbDpwYXNzd29yZDEk
+spring:
+  datasource:
+    hikari:
+      jdbcUrl: jdbc:mariadb://mariadb:3306/requestdb
+      username: requestuser
+      password: request123
+      driver-class-name: org.mariadb.jdbc.Driver
+      pool-name: reqdb-pool
+      registerMbeans: true
+  jpa:
+    generate-ddl: false
+    show-sql: false
+    hibernate:
+      ddl-auto: validate
+      naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
+      enable-lazy-load-no-trans: true
+    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+  security:
+    usercredentials:
+    -
+      username: bpel
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: BPEL-Client
+    -
+      username: mso_admin
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: ACTUATOR
+
+#Actuator
+management:
+  context-path: /manage
+
+flyway:
+  baseline-on-migrate: true
+  url: jdbc:mariadb://mariadb:3306/requestdb
+  user: reqeustuser
+  password: request123
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/override-files/sdc-controller/onapheat/override.yaml b/plans/usecases/pnf-sw-upgrade/so/config/override-files/sdc-controller/onapheat/override.yaml
new file mode 100755 (executable)
index 0000000..ed8bd43
--- /dev/null
@@ -0,0 +1,81 @@
+aai:
+  auth: 2A11B07DB6214A839394AA1EC5844695F5114FC407FF5422625FB00175A3DCB8A1FF745F22867EFA72D5369D599BBD88DA8BED4233CF5586
+server:
+  port: 8085
+
+spring:
+  datasource:
+    hikari:
+      jdbcUrl: jdbc:mariadb://mariadb:3306/catalogdb
+      username: cataloguser
+      password: catalog123
+      driver-class-name: org.mariadb.jdbc.Driver
+      pool-name: catdb-pool
+      registerMbeans: false
+
+  security:
+    usercredentials:
+    -
+      username: asdc
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: Asdc-Client
+    -
+      username: mso_admin
+      password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+      role: ACTUATOR
+
+request:
+  datasource:
+    hikari:
+      jdbcUrl: jdbc:mariadb://mariadb:3306/requestdb
+      username: requestuser
+      password: request123
+      driver-class-name: org.mariadb.jdbc.Driver
+      pool-name: reqdb-pool
+      registerMbeans: false
+
+mso:
+  msoKey: 07a7159d3bf51a0e53be7a8f89699be7
+  logPath: ./logs/asdc
+  catalog:
+    db:
+      spring:
+        endpoint: http://catalog-db-adapter:8082
+  db:
+    auth: Basic YnBlbDpwYXNzd29yZDEk
+  site-name: onapheat
+  camundaURL: http://bpmn-infra:8081/
+  adapters:
+    requestDb:
+      endpoint: http://request-db-adapter:8083
+      auth: Basic YnBlbDpwYXNzd29yZDEk
+  aai:
+    endpoint: https://aai.api.simpledemo.onap.org:8443
+  asdc-connections:
+    asdc-controller1:
+      user: mso
+      consumerGroup: SO-OpenSource-Env11
+      consumerId: SO-COpenSource-Env11
+      environmentName: AUTO
+      asdcAddress: c2.vm1.sdc.simpledemo.onap.org:8443
+      password: 76966BDD3C7414A03F7037264FF2E6C8EEC6C28F2B67F2840A1ED857C0260FEE731D73F47F828E5527125D29FD25D3E0DE39EE44C058906BF1657DE77BF897EECA93BDC07FA64F
+      pollingInterval: 60
+      pollingTimeout: 60
+      relevantArtifactTypes: HEAT,HEAT_ENV,HEAT_VOL
+      useHttpsWithDmaap: false
+      activateServerTLSAuth: false
+      keyStorePassword:
+      keyStorePath:
+      watchDogTimeout: 100
+      isFitlerInEmptyResources: true
+      messageBusAddress: vm1.mr.simpledemo.onap.org,vm1.mr.simpledemo.onap.org
+  asdc:
+    config:
+      activity:
+        endpoint: http://sdc-wfd-be:8080
+      key: 566B754875657232314F5548556D3665
+      components:
+        count: 0,
+        componentNames:
+  scheduling:
+    enabled: false
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/override-files/so-monitoring/onapheat/override.yaml b/plans/usecases/pnf-sw-upgrade/so/config/override-files/so-monitoring/onapheat/override.yaml
new file mode 100755 (executable)
index 0000000..7e61c7d
--- /dev/null
@@ -0,0 +1,24 @@
+server:
+  port: 30224
+  tomcat:
+    max-threads: 4
+ssl-enable: false
+camunda:
+  rest:
+    api:
+      url: http://bpmn-infra:8081/sobpmnengine/engine/
+      engine: default
+      auth: Basic YXBpaEJwbW46cGFzc3dvcmQxJA==
+mso:
+  database:
+    rest:
+      api:
+        url: http://request-db-adapter:8083/infraActiveRequests/
+        auth: Basic YnBlbDpwYXNzd29yZDEk
+spring:
+ security:
+   usercredentials:
+   -
+     username: gui
+     password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+     role: GUI-Client
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/override-files/so-vnfm-adapter/onapheat/override.yaml b/plans/usecases/pnf-sw-upgrade/so/config/override-files/so-vnfm-adapter/onapheat/override.yaml
new file mode 100755 (executable)
index 0000000..bb71512
--- /dev/null
@@ -0,0 +1,30 @@
+server:
+    port: 9092
+    tomcat:
+        max-threads: 4
+    ssl:
+        key-alias: so@so.onap.org
+        key--store-password: 'ywsqCy:EEo#j}HJHM7z^Rk[L'
+        key-store: classpath:so-vnfm-adapter.p12
+        key-store-type: PKCS12
+        client-auth: need
+
+http:
+  client:
+    ssl:
+      trust-store: classpath:org.onap.so.trust.jks
+      trust-store-password: ',sx#.C*W)]wVgJC6ccFHI#:H'
+aai:
+  auth: 221187EFA3AD4E33600DE0488F287099934CE65C3D0697BCECC00BB58E784E07CD74A24581DC31DBC086FF63DF116378776E9BE3D1325885
+  version: v15
+  endpoint:  https://aai-simulator:9993
+mso:
+  key: 07a7159d3bf51a0e53be7a8f89699be7
+sdc:
+  username: mso
+  password: 76966BDD3C7414A03F7037264FF2E6C8EEC6C28F2B67F2840A1ED857C0260FEE731D73F47F828E5527125D29FD25D3E0DE39EE44C058906BF1657DE77BF897EECA93BDC07FA64F
+  key: 566B754875657232314F5548556D3665
+  endpoint: http://sdc-simulator:9991/
+  toscametapath: Artifacts/Deployment/OTHER/TOSCA.meta
+vnfmadapter:
+  endpoint: https://so-vnfm-adapter:9092
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/override-files/vnfm-simulator/onapheat/override.yaml b/plans/usecases/pnf-sw-upgrade/so/config/override-files/vnfm-simulator/onapheat/override.yaml
new file mode 100755 (executable)
index 0000000..05cb1e5
--- /dev/null
@@ -0,0 +1,56 @@
+spring:
+ h2:
+  console:
+  enabled: true
+  path: console
+ datasource:
+  url: jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
+  username: admin
+  password: admin
+ http:
+  converters:
+   preferred-json-mapper: gson
+ security:
+  usercredentials:
+   - username: vnfm
+     password: '$2a$10$Fh9ffgPw2vnmsghsRD3ZauBL1aKXebigbq3BB1RPWtE62UDILsjke'
+     role: BPEL-Client
+
+server:
+  port: 9093
+  tomcat:
+    max-threads: 50
+  ssl:
+    client-auth: need
+    key-alias: so@so.onap.org
+    key--store-password: '7Em3&j4.19xYiMelhD5?xbQ.'
+    key-store: classpath:so-vnfm-simulator.p12
+    key-store-type: PKCS12
+  request:
+    grant:
+      auth: twowaytls
+  dns:
+    name: so-vnfm-simulator
+
+vnfds:
+  vnfdlist:
+  -  vnfdid: sgsn-mme_12df452s04131
+     vnfclist:
+     - vnfcid: VNFC1
+       resourceTemplateId: vnfd1_vnfc1
+       vduId: vnfd1_vduForVnfc1
+       type: COMPUTE
+     - vnfcid: VNFC2
+       resourceTemplateId: vnfd1_vnfc2
+       vduId: vnfd1_vduForVnfc2
+       type: COMPUTE
+  -  vnfdid: 2
+     vnfclist:
+     - vnfcid: VNFC3
+       resourceTemplateId: vnfd2_vnfc3
+       vduId: vnfd2_vduForVnfc3
+       type: COMPUTE
+     - vnfcid: VNFC4
+       resourceTemplateId: vnfd2_vnfc4
+       vduId: vnfd2_vduForVnfc4
+       type: COMPUTE
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/populate-aai-simulator.sh b/plans/usecases/pnf-sw-upgrade/so/config/populate-aai-simulator.sh
new file mode 100755 (executable)
index 0000000..6852e3f
--- /dev/null
@@ -0,0 +1,171 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 Nordix Foundation.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# @author Gareth Roper (gareth.roper@est.tech)
+# @auther Waqas Ikram (waqas.ikram@est.tech)
+
+SCRIPT_NAME=$(basename $0)
+SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+WAIT_FOR_SCRIPT=$SCRIPT_HOME/wait-for.sh
+
+current_timestamp()
+{
+ date +"%Y-%m-%d %H:%M:%S"
+}
+
+populate_aai_simulator()
+{
+ $WAIT_FOR_SCRIPT -t "$TIMEOUT_IN_SECONDS" -h "$AAI_SIMULATOR_HOST" -p "$AAI_SIMULATOR_PORT"
+
+ if [ $?  -eq 0 ]
+ then
+     echo "$SCRIPT_NAME $(current_timestamp): AAI Simulator is Running."
+ else
+     echo "$SCRIPT_NAME $(current_timestamp): AAI Simulator could not be found. Exiting..."
+     exit 1
+ fi
+
+ BASE_URL="https://$AAI_SIMULATOR_HOST:$AAI_SIMULATOR_PORT/aai/v15"
+ BASIC_AUTHORIZATION_HEADER="Authorization: Basic YWFpOmFhaS5vbmFwLm9yZzpkZW1vMTIzNDU2IQ=="
+ APPICATION_JSON="application/json"
+ ACCEPT_HEADER="Accept: $APPICATION_JSON"
+ CONTENT_TYPE_HEADER="Content-Type: $APPICATION_JSON"
+ CURL_COMMAND="curl -k -H $BASIC_AUTHORIZATION_HEADER -H $ACCEPT_HEADER -H $CONTENT_TYPE_HEADER"
+
+ AAI_SIMULATOR_DATA_DIR=$SCRIPT_HOME/aai-simulator-populate-data
+ CUSTOMER_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/customer.json
+ PROJECT_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/project.json
+ OWNING_ENTITY_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/owning-entity.json
+ LINE_OF_BUSINESS_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/line-of-business.json
+ PLATFORM_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/platform.json
+ CLOUD_REGION_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/cloud-region.json
+ TENANT_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/tenant.json
+ ESR_VNFM_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/esr-vnfm.json
+ ESR_SYSTEM_INFO_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/esr-system-info.json
+ CLOUD_ESR_SYSTEM_INFO_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/cloud-esr-system-info.json
+ PNF_JSON_FILE=$AAI_SIMULATOR_DATA_DIR/pnf.json
+ STATUS_CODE_ACCEPTED="202"
+
+ echo "$SCRIPT_NAME $(current_timestamp): checking health of AAI Simulator"
+ response=$(curl -k $BASE_URL/healthcheck)
+
+ if [[ "$response" -ne "healthy" ]] ; then
+       echo "$SCRIPT_NAME $(current_timestamp) ERROR: AAI Simulator health check failed. Response: $response"
+       exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): AAI Simulator is healthy"
+
+ echo "$SCRIPT_NAME $(current_timestamp): Populating AAI Simulator"
+
+ echo "$SCRIPT_NAME $(current_timestamp): Adding Cloud-Customer Data"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/business/customers/customer/DemoCustomer -X PUT -d @"$CUSTOMER_JSON_FILE")
+
+ if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put customer data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): Adding Project"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/business/projects/project/PnfSwUCsitProject -X PUT -d @"$PROJECT_JSON_FILE")
+
+ if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put project data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+  echo "$SCRIPT_NAME $(current_timestamp): Adding Owning-Entity"
+  status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/business/owning-entities/owning-entity/f2e1071e-3d47-4a65-94d4-e473ec03326a -X PUT -d @$"$OWNING_ENTITY_JSON_FILE")
+
+  if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put owning entity data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): Adding Line Of Business"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/business/lines-of-business/line-of-business/PnfSwUCsitLineOfBusiness -X PUT -d @$"$LINE_OF_BUSINESS_JSON_FILE")
+
+ if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put line of business data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): Adding Platform"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/business/platforms/platform/PnfSwUCsitPlatform -X PUT -d @$"$PLATFORM_JSON_FILE")
+
+ if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put platform data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): Adding Cloud Region"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/PnfSwUCloudRegion -X PUT -d @$"$CLOUD_REGION_JSON_FILE")
+
+  if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put Cloud Region data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): Adding Tenant"
+  status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/PnfSwUCloudRegion/tenants/tenant/693c7729b2364a26a3ca602e6f66187d -X PUT -d @$"$TENANT_JSON_FILE")
+
+  if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put Tenant data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): Adding esr-vnfm"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/external-system/esr-vnfm-list/esr-vnfm/c5e99cee-1996-4606-b697-838d51d4e1a3 -X PUT -d @$"$ESR_VNFM_JSON_FILE")
+
+  if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put esr-vnfm data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+  echo "$SCRIPT_NAME $(current_timestamp): Adding esr-system-info"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/external-system/esr-vnfm-list/esr-vnfm/c5e99cee-1996-4606-b697-838d51d4e1a3/esr-system-info-list/esr-system-info/5c067098-f2e3-40f7-a7ba-155e7c61e916 -X PUT -d @$"$ESR_SYSTEM_INFO_JSON_FILE")
+
+  if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put esr-system-info data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+  echo "$SCRIPT_NAME $(current_timestamp): Adding cloud esr-system-info"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/PnfSwUCloudRegion/esr-system-info-list/esr-system-info/e6a0b318-9756-4f11-94e8-919312d6c2bd -X PUT -d @$"$CLOUD_ESR_SYSTEM_INFO_JSON_FILE")
+
+  if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put cloud esr-system-info data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+  echo "$SCRIPT_NAME $(current_timestamp): Adding PNF"
+ status_code=$(curl -k --write-out %{http_code} --silent --output /dev/null -H "$BASIC_AUTHORIZATION_HEADER" -H "$ACCEPT_HEADER" -H "$CONTENT_TYPE_HEADER" $BASE_URL/network/pnfs/pnf/PNFDemo -X PUT -d @$"$PNF_JSON_FILE")
+
+  if [[ "$status_code" -ne "$STATUS_CODE_ACCEPTED" ]] ; then
+     echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to put PNF data in AAI Simulator. Status code received: $status_code"
+     exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): AAI Simulator Populated Successfully"
+}
+
+# main body
+populate_aai_simulator
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/wait-for-aai-config-job.sh b/plans/usecases/pnf-sw-upgrade/so/config/wait-for-aai-config-job.sh
new file mode 100755 (executable)
index 0000000..58a0781
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 Nordix Foundation.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# @author Waqas Ikram (waqas.ikram@est.tech)
+
+SLEEP_TIME=5
+SUCCESSFUL_TEXT="AAI Simulator Populated Successfully"
+FAILURE_TEXT="ERROR:"
+TIME_OUT_TEXT="Time out"
+CONTAINER_NAME=$(docker ps -aqf "name=populate-aai-config" --format "{{.Names}}")
+SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+SCRIPT_NAME=$(basename $0)
+
+current_timestamp()
+{
+ date +"%Y-%m-%d %H:%M:%S"
+}
+
+# main body
+if [ -z $TIME_OUT_DEFAULT_VALUE_SEC ]; then
+    echo "$SCRIPT_NAME $(current_timestamp): ERROR: Undefined value for TIME_OUT_DEFAULT_VALUE_SEC attribute"
+    exit 1
+fi
+
+if [ -z $CONTAINER_NAME ]; then
+   echo "$SCRIPT_NAME $(current_timestamp): Unable to find docker container id "
+   exit 1
+fi
+
+START_TIME_IN_SECONDS=`date +%s`
+TIME_OUT_END_TIME_IN_SECONDS=$(($START_TIME_IN_SECONDS+$TIME_OUT_DEFAULT_VALUE_SEC));
+
+
+echo echo "$SCRIPT_NAME $(current_timestamp): $SCRIPT_NAME script Start Time `date -d @$START_TIME_IN_SECONDS`"
+echo echo "$SCRIPT_NAME $(current_timestamp): $SCRIPT_NAME will time out at `date -d @$TIME_OUT_END_TIME_IN_SECONDS`"
+
+while [ `date +%s` -lt "$TIME_OUT_END_TIME_IN_SECONDS" ]; do
+    echo "$(current_timestamp): Waiting for $CONTAINER_NAME to finish ..."
+
+    result=$(docker logs $CONTAINER_NAME 2>&1 | grep -E "$SUCCESSFUL_TEXT|$FAILURE_TEXT|$TIME_OUT_TEXT")
+    if [ ! -z "$result" ]; then
+        echo "$SCRIPT_NAME $(current_timestamp): Found result: $result"
+        break;
+    fi
+    echo "$(current_timestamp): Sleeping for ${SLEEP_TIME} seconds"
+    sleep ${SLEEP_TIME}
+done
+
+if [ -z "$result" ]; then
+   echo "$SCRIPT_NAME $(current_timestamp): ERROR: failed to populate AAI Simulator . . . "
+   echo "-------------- $CONTAINER_NAME logs -------------"
+   docker logs $CONTAINER_NAME
+   echo "------------------------------------------------------------"
+   exit 1
+fi
+
+if echo "$result" | grep -E "$FAILURE_TEXT|$TIME_OUT_TEXT"; then
+    echo "$SCRIPT_NAME $(current_timestamp): populate-aai-simulator.sh failed"
+    echo "-------------- $CONTAINER_NAME logs -------------"
+    docker logs $CONTAINER_NAME
+    echo "------------------------------------------------------------"
+    exit 1
+fi
+
+echo "$SCRIPT_NAME $(current_timestamp): Successfully populated AAI Simulator . . ."
+exit 0
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/wait-for-container.sh b/plans/usecases/pnf-sw-upgrade/so/config/wait-for-container.sh
new file mode 100755 (executable)
index 0000000..35ee264
--- /dev/null
@@ -0,0 +1,153 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 Nordix Foundation.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# @author Waqas Ikram (waqas.ikram@est.tech)
+
+SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+SCRIPT_NAME=$(basename $0)
+WAIT_FOR_SCRIPT=$SCRIPT_HOME/wait-for.sh
+
+# Process the arguments passed to the script
+usage()
+{
+ _msg_="$@"
+ cat<<-EOF
+ Command Arguments:
+
+ -c, --container-name
+ Mandatory argument. container name
+
+ -n, --network-name
+ Mandatory argument. network name
+
+ -t, --timeout
+ Mandatory argument. time out value in seconds (must be number)
+
+ --help
+ Optional argument.  Display this usage.
+
+EOF
+ exit 1
+}
+
+current_timestamp()
+{
+ date +"%Y-%m-%d %H:%M:%S"
+}
+
+# Called when script is executed with invalid arguments
+invalid_arguments()
+{
+ echo "Missing or invalid option(s):"
+ echo "$@"
+ echo "Try --help for more information"
+ exit 1
+}
+
+process_arguments()
+{
+ SHORT_ARGS="c:n:t:"
+ LONG_ARGS="help,container-name:,network-name:,timeout:"
+
+ args=$(getopt -o $SHORT_ARGS -l $LONG_ARGS -n "$0"  -- "$@"  2>&1 )
+ [[ $? -ne 0 ]] && invalid_arguments $( echo " $args"| head -1 )
+ [[ $# -eq 0 ]] && invalid_arguments "No options provided"
+
+ eval set -- "$args"
+ cmd_arg="$0"
+
+ while true; do
+    case "$1" in
+         -c|--container-name)
+          NAME=$2
+          shift 2 ;;
+         -n|--network-name)
+          NETWORK_NAME=$2
+          shift 2 ;;
+          -t|--timeout)
+          TIME_OUT=$2
+          shift 2 ;;
+         --help)
+          usage
+          exit 0
+          ;;
+         --)
+          shift
+          break ;;
+         *)
+          echo BAD ARGUMENTS # perhaps error
+          break ;;
+      esac
+ done
+
+ if [ -z "$NAME" ]; then
+   echo "$SCRIPT_NAME $(current_timestamp): error: Container name  must not be empty! $NAME" >&2; exit 1
+ fi
+
+ if [ -z "$NETWORK_NAME" ]; then
+   echo "$SCRIPT_NAME $(current_timestamp): error: network name  must not be empty! $NETWORK_NAME" >&2; exit 1
+ fi
+
+ regex='^[0-9]+$'
+ if ! [[ $TIME_OUT =~ $regex ]] ; then
+   echo "$SCRIPT_NAME $(current_timestamp): error: TIME_OUT must be number $TIME_OUT" >&2; exit 1
+ fi
+
+ CONTAINER_NAME=$(docker ps -aqf "name=$NAME" --format "{{.Names}}")
+
+ if [ $? -ne 0 ]; then
+   echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to find container using $NAME"
+   exit 1
+ fi
+
+ result=$(docker inspect --format '{{.State.Running}}' $CONTAINER_NAME)
+
+ if [ $result != "true" ] ; then
+  echo "$SCRIPT_NAME $(current_timestamp) ERROR: $CONTAINER_NAME container is not running"
+  exit 1
+ fi
+
+ HOST_IP=$(docker inspect --format '{{ index .NetworkSettings.Networks "'$NETWORK_NAME'" "IPAddress"}}' $CONTAINER_NAME)
+
+ if [ $? -ne 0 ] || [ -z $HOST_IP ] ; then
+   echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to find HOST IP using network name: $NETWORK_NAME and container name: $CONTAINER_NAME"
+   exit 1
+ fi
+
+ PORT=$(docker port $CONTAINER_NAME | cut -c1-$(docker port $CONTAINER_NAME | grep -aob '/' | grep -oE '[0-9]+'))
+
+ if [ $? -ne 0 ] || [ -z $PORT ] ; then
+   echo "$SCRIPT_NAME $(current_timestamp) ERROR: Unable to find PORT using project name: $PROJECT_NAME and container name: $CONTAINER_NAME"
+   exit 1
+ fi
+
+ $WAIT_FOR_SCRIPT -t "$TIME_OUT" -h "$HOST_IP" -p "$PORT"
+
+ if [ $? -ne 0 ]; then
+   echo "$SCRIPT_NAME $(current_timestamp) ERROR: wait-for.sh failed ..."
+   exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): finished successfully"
+}
+
+# main body
+process_arguments $@
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/wait-for-workaround-job.sh b/plans/usecases/pnf-sw-upgrade/so/config/wait-for-workaround-job.sh
new file mode 100755 (executable)
index 0000000..035c5e2
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 Nordix Foundation.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# @author Waqas Ikram (waqas.ikram@est.tech)
+
+SLEEP_TIME=5
+WORKAROUND_SUCCESSFUL_TEXT="Finished applying workaround"
+WORKAROUND_FAILURE_TEXT="Failed to execute workaround"
+WORKAROUND_TIME_OUT_TEXT="workaround script timed out"
+WORKAROUND_CONTAINER_NAME=$(docker ps -aqf "name=workaround-config" --format "{{.Names}}")
+SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+SCRIPT_NAME=$(basename $0)
+
+current_timestamp()
+{
+ date +"%Y-%m-%d %H:%M:%S"
+}
+
+# main body
+if [ -z $TIME_OUT_DEFAULT_VALUE_SEC ]; then
+    echo "$SCRIPT_NAME $(current_timestamp): ERROR: Undefined value for TIME_OUT_DEFAULT_VALUE_SEC attribute"
+    exit 1
+fi
+
+if [ -z $WORKAROUND_CONTAINER_NAME ]; then
+   echo "$SCRIPT_NAME $(current_timestamp): Unable to find docker container id "
+   exit 1
+fi
+
+START_TIME_IN_SECONDS=`date +%s`
+TIME_OUT_END_TIME_IN_SECONDS=$(($START_TIME_IN_SECONDS+$TIME_OUT_DEFAULT_VALUE_SEC));
+
+
+echo echo "$SCRIPT_NAME $(current_timestamp): $SCRIPT_NAME script Start Time `date -d @$START_TIME_IN_SECONDS`"
+echo echo "$SCRIPT_NAME $(current_timestamp): $SCRIPT_NAME will time out at `date -d @$TIME_OUT_END_TIME_IN_SECONDS`"
+
+while [ `date +%s` -lt "$TIME_OUT_END_TIME_IN_SECONDS" ]; do
+    echo "$(current_timestamp): Waiting for $WORKAROUND_CONTAINER_NAME to finish ..."
+
+    result=$(docker logs $WORKAROUND_CONTAINER_NAME 2>&1 | grep -E "$WORKAROUND_SUCCESSFUL_TEXT|$WORKAROUND_FAILURE_TEXT|$WORKAROUND_TIME_OUT_TEXT")
+    if [ ! -z "$result" ]; then
+        echo "$SCRIPT_NAME $(current_timestamp): Found result: $result"
+        break;
+    fi
+    echo "$(current_timestamp): Sleeping for ${SLEEP_TIME} seconds"
+    sleep ${SLEEP_TIME}
+done
+
+if [ -z "$result" ]; then
+   echo "$SCRIPT_NAME $(current_timestamp): ERROR: failed to apply workaround . . . "
+   echo "-------------- $WORKAROUND_CONTAINER_NAME logs -------------"
+   docker logs $WORKAROUND_CONTAINER_NAME
+   echo "------------------------------------------------------------"
+   exit 1
+fi
+
+if echo "$result" | grep -E "$WORKAROUND_FAILURE_TEXT|$WORKAROUND_TIME_OUT_TEXT"; then
+    echo "$SCRIPT_NAME $(current_timestamp): Work around script failed"
+    echo "-------------- $WORKAROUND_CONTAINER_NAME logs -------------"
+    docker logs $WORKAROUND_CONTAINER_NAME
+    echo "------------------------------------------------------------"
+    exit 1
+fi
+
+echo "$SCRIPT_NAME $(current_timestamp): Successfully applied workaround configuration . . ."
+exit 0
diff --git a/plans/usecases/pnf-sw-upgrade/so/config/wait-for.sh b/plans/usecases/pnf-sw-upgrade/so/config/wait-for.sh
new file mode 100755 (executable)
index 0000000..53581b3
--- /dev/null
@@ -0,0 +1,138 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 Nordix Foundation.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# @author Waqas Ikram (waqas.ikram@est.tech)
+
+SCRIPT_NAME=$(basename $0)
+
+# Process the arguments passed to the script
+usage()
+{
+ _msg_="$@"
+ cat<<-EOF
+ Command Arguments:
+
+ -t, --timeout
+ Mandatory argument. time out value in seconds (must be number) 
+
+ -h --host
+ Mandatory argument. Host name or IP
+
+ -p, --port
+ Mandatory argument. Port of the host
+
+ --help
+ Optional argument.  Display this usage.
+
+EOF
+ exit 1
+}
+
+current_timestamp()
+{
+ date +"%Y-%m-%d %H:%M:%S"
+}
+
+# Called when script is executed with invalid arguments
+invalid_arguments()
+{
+ echo "Missing or invalid option(s):"
+ echo "$@"
+ echo "Try --help for more information"
+ exit 1
+}
+
+process_arguments()
+{
+ SHORT_ARGS="t:h:p:"
+ LONG_ARGS="help,timeout:,host:,port:"
+
+ args=$(getopt -o $SHORT_ARGS -l $LONG_ARGS -n "$0"  -- "$@"  2>&1 )
+ [[ $? -ne 0 ]] && invalid_arguments $( echo " $args"| head -1 )
+ [[ $# -eq 0 ]] && invalid_arguments "No options provided"
+
+ eval set -- "$args"
+ cmd_arg="$0"
+
+ while true; do
+    case "$1" in
+         -t|--timeout)
+          TIME_OUT=$2
+          shift 2 ;;
+          -h|--host)
+          HOST=$2
+          shift 2 ;;
+          -p|--port)
+          PORT=$2
+         shift 2 ;;
+         --help)
+          usage
+          exit 0
+          ;;
+         --)
+          shift
+          break ;;
+         *)
+          echo BAD ARGUMENTS # perhaps error
+          break ;;
+      esac
+ done
+
+ regex='^[0-9]+$'
+ if ! [[ $TIME_OUT =~ $regex ]] ; then
+   echo "$SCRIPT_NAME $(current_timestamp): error: TIME_OUT must be number $TIME_OUT" >&2; exit 1
+ fi
+
+ if [ -z "$HOST" ]; then
+   echo "$SCRIPT_NAME $(current_timestamp): error: HOST must not be empty! $HOST" >&2; exit 1
+ fi
+
+ if ! [[ $PORT =~ $regex ]]; then
+   echo "$SCRIPT_NAME $(current_timestamp): error: PORT must be number! $PORT" >&2; exit 1
+ fi
+
+ SLEEP_TIME=5
+ START_TIME_IN_SECONDS=`date +%s`
+ TIME_OUT_END_TIME_IN_SECONDS=$(($START_TIME_IN_SECONDS+$TIME_OUT));
+
+ while [ `date +%s` -lt "$TIME_OUT_END_TIME_IN_SECONDS" ]; do
+    echo "$(current_timestamp): Waiting for $HOST:$PORT to startup ..."
+
+    nc -z "$HOST" "$PORT" > /dev/null 2>&1
+    result=$?
+    if [ $result -eq 0 ] ; then
+        echo "$SCRIPT_NAME $(current_timestamp): $HOST:$PORT is up and running"
+        break;
+    fi
+    echo "$SCRIPT_NAME $(current_timestamp): Sleeping for ${SLEEP_TIME} seconds"
+    sleep ${SLEEP_TIME}
+ done
+
+ if [ $result -ne 0 ]; then
+    echo "$SCRIPT_NAME $(current_timestamp): Time out: could not get any response from $HOST:$PORT . . ."
+    exit 1
+ fi
+
+ echo "$SCRIPT_NAME $(current_timestamp): finished successfully"
+}
+
+# main body
+process_arguments $@
diff --git a/plans/usecases/pnf-sw-upgrade/so/docker-compose.local.yml b/plans/usecases/pnf-sw-upgrade/so/docker-compose.local.yml
new file mode 100755 (executable)
index 0000000..1e56822
--- /dev/null
@@ -0,0 +1,25 @@
+version: '3'
+services:
+################################################################################
+  mariadb:
+    image: mariadb:10.1.11
+################################################################################
+  catalog-db-adapter:
+    image: onap/so/catalog-db-adapter:${TAG}
+################################################################################
+  request-db-adapter:
+    image: onap/so/request-db-adapter:${TAG}
+################################################################################
+  sdnc-adapter:
+    image: onap/so/sdnc-adapter:${TAG}
+################################################################################
+  sdc-controller:
+    image: onap/so/sdc-controller:${TAG}
+################################################################################
+  bpmn-infra:
+    image: onap/so/bpmn-infra:${TAG}
+################################################################################
+  api-handler-infra:
+    image: onap/so/api-handler-infra:${TAG}
+#############################################################################
+
diff --git a/plans/usecases/pnf-sw-upgrade/so/docker-compose.yml b/plans/usecases/pnf-sw-upgrade/so/docker-compose.yml
new file mode 100755 (executable)
index 0000000..bea0dca
--- /dev/null
@@ -0,0 +1,299 @@
+version: '3'
+services:
+################################################################################
+  mariadb:
+    image: ${NEXUS_DOCKER_REPO_MSO}/mariadb:10.1.11
+    ports:
+      - "3306:3306"
+    container_name: mariadb
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${TEST_LAB_DIR}/volumes/mariadb/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
+      - ${TEST_LAB_DIR}/volumes/mariadb/conf.d:/etc/mysql/conf.d
+    environment:
+      - MYSQL_ROOT_PASSWORD=password
+    hostname:
+      mariadb.so.testlab.onap.org
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+################################################################################
+  catalog-db-adapter:
+    image: ${NEXUS_DOCKER_REPO_MSO}/onap/so/catalog-db-adapter:${TAG}
+    ports:
+      - "8082:8082"
+    container_name: catalog-db-adapter
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${TEST_LAB_DIR}/volumes/so/ca-certificates/onapheat:/app/ca-certificates
+      - ${CONFIG_DIR_PATH}/override-files/catalog-db-adapter/onapheat:/app/config
+    environment:
+      - APP=catalog-db-adapter
+      - JVM_ARGS=-Xms64m -Xmx512m
+      - DB_HOST=mariadb
+      - DB_PORT=3306
+      - DB_USERNAME=root
+      - DB_PASSWORD=password
+      - DB_ADMIN_USERNAME=root
+      - DB_ADMIN_PASSWORD=password
+    hostname:
+      catalog-db-adapter.so.testlab.onap.org
+    depends_on:
+      - mariadb
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+    command:
+      - /app/wait-for.sh
+      - -q
+      - -t
+      - "300"
+      - mariadb:3306
+      - --
+      - "/app/start-app.sh"
+################################################################################
+  request-db-adapter:
+    image: ${NEXUS_DOCKER_REPO_MSO}/onap/so/request-db-adapter:${TAG}
+    container_name: request-db-adapter
+    ports:
+      - "8083:8083"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${TEST_LAB_DIR}/volumes/so/ca-certificates/onapheat:/app/ca-certificates
+      - ${CONFIG_DIR_PATH}/override-files/request-db-adapter/onapheat:/app/config
+    environment:
+      - APP=request-db-adapter
+      - JVM_ARGS=-Xms64m -Xmx512m
+      - DB_HOST=mariadb
+      - DB_PORT=3306
+      - DB_USERNAME=root
+      - DB_PASSWORD=password
+      - DB_ADMIN_USERNAME=root
+      - DB_ADMIN_PASSWORD=password
+    hostname:
+      request-db-adapter.so.testlab.onap.org
+    depends_on:
+      - mariadb
+      - catalog-db-adapter
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+    command:
+      - /app/wait-for.sh
+      - -q
+      - -t
+      - "300"
+      - catalog-db-adapter:8082
+      - --
+      - "/app/start-app.sh"
+################################################################################
+  sdnc-adapter:
+    image: ${NEXUS_DOCKER_REPO_MSO}/onap/so/sdnc-adapter:${TAG}
+    container_name: sdnc-adapter
+    ports:
+      - "8086:8086"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${TEST_LAB_DIR}/volumes/so/ca-certificates/onapheat:/app/ca-certificates
+      - ${TEST_LAB_DIR}/volumes/so/config/sdnc-adapter/onapheat:/app/config
+    environment:
+      - APP=sdnc-adapter
+      - JVM_ARGS=-Xms64m -Xmx512m
+      - DB_HOST=mariadb
+      - DB_PORT=3306
+      - DB_USERNAME=root
+      - DB_PASSWORD=password
+      - DB_ADMIN_USERNAME=root
+      - DB_ADMIN_PASSWORD=password
+    hostname:
+      sdnc-adapter.so.testlab.onap.org
+    depends_on:
+      - mariadb
+      - catalog-db-adapter
+      - request-db-adapter
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+    command:
+      - /app/wait-for.sh
+      - -q
+      - -t
+      - "300"
+      - request-db-adapter:8083
+      - --
+      - "/app/start-app.sh"
+################################################################################
+  sdc-controller:
+    image: ${NEXUS_DOCKER_REPO_MSO}/onap/so/sdc-controller:${TAG}
+    container_name: sdc-controller
+    ports:
+      - "8085:8085"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${TEST_LAB_DIR}/volumes/so/ca-certificates/onapheat:/app/ca-certificates
+      - ${CONFIG_DIR_PATH}/distribution-test-zip/zipped_sdc_csar.tar.gz:/distribution-test-zip/zipped_sdc_csar.tar.gz
+      - ${CONFIG_DIR_PATH}/override-files/sdc-controller/onapheat:/app/config
+    environment:
+      - APP=sdc-controller
+      - JVM_ARGS=-Xms64m -Xmx512m
+      - DB_HOST=mariadb
+      - DB_PORT=3306
+      - DB_USERNAME=root
+      - DB_PASSWORD=password
+      - DB_ADMIN_USERNAME=root
+      - DB_ADMIN_PASSWORD=password
+    hostname:
+      sdc-controller.so.testlab.onap.org
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+    entrypoint:
+      - /bin/sh
+      - -c
+      - 'mkdir -p /app/distribution-test-zip/unzipped && cp -R /distribution-test-zip/zipped_sdc_csar.tar.gz /app && tar -xvzf /app/zipped_sdc_csar.tar.gz -C /app/distribution-test-zip/unzipped && /app/wait-for.sh -q -t "300" request-db-adapter:8083 -- "/app/start-app.sh"'
+################################################################################
+  bpmn-infra:
+    user: root
+    image: ${NEXUS_DOCKER_REPO_MSO}/onap/so/bpmn-infra:${TAG}
+    container_name: bpmn-infra
+    ports:
+      - "8081:8081"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${TEST_LAB_DIR}/volumes/so/ca-certificates/onapheat:/app/ca-certificates
+      - ${CONFIG_DIR_PATH}/override-files/bpmn-infra/onapheat:/app/config
+      - ${CONFIG_DIR_PATH}/certificates/aai-certificate/aai.cert:/app/ca-certificates/aai.cert
+    environment:
+      - APP=bpmn-infra
+      - JVM_ARGS=-Xms64m -Xmx512m
+      - DB_HOST=mariadb
+      - DB_PORT=3306
+      - DB_USERNAME=camundauser
+      - DB_PASSWORD=camunda123
+      - DB_ADMIN_USERNAME=root
+      - DB_ADMIN_PASSWORD=password
+    hostname:
+      bpmn-infra.so.testlab.onap.org
+    depends_on:
+      - mariadb
+      - catalog-db-adapter
+      - request-db-adapter
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+    command:
+      - /app/wait-for.sh
+      - -q
+      - -t
+      - "300"
+      - request-db-adapter:8083
+      - --
+      - "/app/start-app.sh"
+################################################################################
+  api-handler-infra:
+    image: ${NEXUS_DOCKER_REPO_MSO}/onap/so/api-handler-infra:${TAG}
+    container_name: api-handler-infra
+    ports:
+      - "8080:8080"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${TEST_LAB_DIR}/volumes/so/ca-certificates/onapheat:/app/ca-certificates
+      - ${CONFIG_DIR_PATH}/override-files/api-handler-infra/onapheat:/app/config
+    environment:
+      - APP=api-handler-infra
+      - JVM_ARGS=-Xms64m -Xmx512m
+      - DB_HOST=mariadb
+      - DB_PORT=3306
+      - DB_USERNAME=root
+      - DB_PASSWORD=password
+      - DB_ADMIN_USERNAME=root
+      - DB_ADMIN_PASSWORD=password
+    hostname:
+      api-handler-infra.so.testlab.onap.org
+    depends_on:
+      - mariadb
+      - catalog-db-adapter
+      - request-db-adapter
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+    command:
+      - /app/wait-for.sh
+      - -q
+      - -t
+      - "300"
+      - request-db-adapter:8083
+      - --
+      - "/app/start-app.sh"
+################################################################################
+  aai-simulator:
+    image: simulators/aai-simulator:latest
+   # image: quay.io/raj_gumma/aai_sim:latest
+    container_name: aai-simulator
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+    ports:
+      - "9993:9993"
+    environment:
+    - APP=AAI-SIMULATOR
+    - JVM_ARGS=-Xms64m -Xmx512m
+    hostname:
+      aai-simulator
+    depends_on:
+      - mariadb
+    logging:
+      driver: "json-file"
+      options:
+        max-size: "30m"
+        max-file: "5"
+################################################################################
+  populate-aai-config:
+    image: jobs/workaround-job-container:latest
+    container_name: populate-aai-config
+    ports:
+       - "9995:9995"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${CONFIG_DIR_PATH}/populate-aai-simulator.sh:/config/populate-aai-simulator.sh
+      - ${CONFIG_DIR_PATH}/wait-for.sh:/config/wait-for.sh
+      - ${CONFIG_DIR_PATH}/aai-simulator-populate-data:/config/aai-simulator-populate-data/
+    environment:
+      - AAI_SIMULATOR_HOST=aai-simulator
+      - AAI_SIMULATOR_PORT=9993
+      - TIMEOUT_IN_SECONDS=300 #5 mins
+    depends_on:
+      - aai-simulator
+    command:
+        - "/config/populate-aai-simulator.sh"
+################################################################################
+  workaround-config:
+    image: jobs/workaround-job-container:latest
+    container_name: workaround-config
+    ports:
+       - "9990:9990"
+    volumes:
+      - /etc/localtime:/etc/localtime:ro
+      - ${CONFIG_DIR_PATH}/apply-workarounds.sh:/config/apply-workarounds.sh
+    environment:
+      - MYSQL_ROOT_PASSWORD=password
+      - DB_HOST=mariadb
+      - DB_PORT=3306
+      - CATALOG_DB=catalogdb
+    depends_on:
+      - mariadb
+    command:
+      - "/config/apply-workarounds.sh"
diff --git a/plans/usecases/pnf-sw-upgrade/so/settings.xml b/plans/usecases/pnf-sw-upgrade/so/settings.xml
new file mode 100755 (executable)
index 0000000..5db5298
--- /dev/null
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Copyright (c) 2016-2018 Huawei Technologies Co., Ltd. and others.  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.
+-->
+<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
+
+<localRepository>${user.home}/.m2/repository</localRepository>
+  <profiles>
+    <profile>
+      <id>onap-settings</id>
+      <properties>
+        <onap.nexus.url>https://nexus.onap.org</onap.nexus.url>
+        <onap.nexus.rawrepo.baseurl.upload>https://nexus.onap.org/content/sites/raw</onap.nexus.rawrepo.baseurl.upload>
+        <onap.nexus.rawrepo.baseurl.download>https://nexus.onap.org/service/local/repositories/raw/content</onap.nexus.rawrepo.baseurl.download>
+        <onap.nexus.rawrepo.serverid>ecomp-raw</onap.nexus.rawrepo.serverid>
+
+        <!-- properties for Nexus Docker registry -->
+        <onap.nexus.dockerregistry.daily>nexus3.onap.org:10003</onap.nexus.dockerregistry.daily>
+        <onap.nexus.dockerregistry.release>nexus3.onap.org:10002</onap.nexus.dockerregistry.release>
+        <docker.pull.registry>nexus3.onap.org:10001</docker.pull.registry>
+        <docker.push.registry>nexus3.onap.org:10003</docker.push.registry>
+      </properties>
+    </profile>
+    <profile>
+      <id>onap-snapshots</id>
+      <repositories>
+        <repository>
+          <id>onap-snapshots</id>
+          <name>onap-snapshots</name>
+          <url>https://nexus.onap.org/content/repositories/snapshots/</url>
+          <releases>
+            <enabled>false</enabled>
+          </releases>
+          <snapshots>
+            <enabled>true</enabled>
+          </snapshots>
+        </repository>
+      </repositories>
+      <pluginRepositories>
+        <pluginRepository>
+          <id>onap-snapshots</id>
+          <name>onap-snapshots</name>
+          <url>https://nexus.onap.org/content/repositories/snapshots/</url>
+          <releases>
+            <enabled>false</enabled>
+          </releases>
+          <snapshots>
+            <enabled>true</enabled>
+          </snapshots>
+        </pluginRepository>
+      </pluginRepositories>
+    </profile>
+    <profile>
+      <id>onap-releases</id>
+      <repositories>
+        <repository>
+          <id>onap-releases</id>
+          <name>onap-releases</name>
+          <url>https://nexus.onap.org/content/repositories/releases/</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>false</enabled>
+          </snapshots>
+        </repository>
+      </repositories>
+      <pluginRepositories>
+        <pluginRepository>
+          <id>onap-releases</id>
+          <name>onap-releases</name>
+          <url>https://nexus.onap.org/content/repositories/releases/</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>false</enabled>
+          </snapshots>
+        </pluginRepository>
+      </pluginRepositories>
+    </profile>
+    <profile>
+      <id>onap-public</id>
+      <repositories>
+        <repository>
+          <id>central</id>
+          <url>http://repo1.maven.org/maven2/</url>
+        </repository>
+        <repository>
+          <id>onap-public</id>
+          <name>onap-public</name>
+          <url>https://nexus.onap.org/content/repositories/public/</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>false</enabled>
+          </snapshots>
+        </repository>
+      </repositories>
+      <pluginRepositories>
+        <pluginRepository>
+          <id>central</id>
+          <url>http://repo1.maven.org/maven2/</url>
+        </pluginRepository>
+        <pluginRepository>
+          <id>onap-public</id>
+          <name>onap-public</name>
+          <url>https://nexus.onap.org/content/repositories/public/</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>false</enabled>
+          </snapshots>
+        </pluginRepository>
+      </pluginRepositories>
+    </profile>
+    <profile>
+      <!-- Configure this profile if you have a local nexus cache -->
+      <id>local-public</id>
+      <repositories>
+        <repository>
+          <id>local-public</id>
+          <name>local-public</name>
+          <url>http://nexus-proxy:8081/nexus/content/repositories/public/</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>false</enabled>
+          </snapshots>
+        </repository>
+      </repositories>
+      <pluginRepositories>
+        <pluginRepository>
+          <id>local-public</id>
+          <name>local-public</name>
+          <url>http://nexus-proxy:8081/nexus/content/repositories/public/</url>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+          <snapshots>
+            <enabled>false</enabled>
+          </snapshots>
+        </pluginRepository>
+      </pluginRepositories>
+    </profile>
+  </profiles>
+
+  <activeProfiles>
+    <activeProfile>onap-settings</activeProfile>
+    <activeProfile>onap-snapshots</activeProfile>
+    <activeProfile>onap-releases</activeProfile>
+    <activeProfile>onap-public</activeProfile>
+    <!-- <activeProfile>local-public</activeProfile> -->
+  </activeProfiles>
+
+</settings>
+
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/pom.xml b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/pom.xml
new file mode 100755 (executable)
index 0000000..f7c7bc1
--- /dev/null
@@ -0,0 +1,81 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onap.so.simulators</groupId>
+        <artifactId>simulator</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>aai-simulator</artifactId>
+    <properties>
+        <version.aai.schema>1.0.0</version.aai.schema>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>${project.parent.groupId}</groupId>
+            <artifactId>common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.aai.schema-service</groupId>
+            <artifactId>aai-schema</artifactId>
+            <version>${version.aai.schema}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-module-jaxb-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.activation</groupId>
+            <artifactId>activation</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>org.onap.so.aaisimulator.AaiSimulatorApplication</mainClass>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/AaiSimulatorApplication.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/AaiSimulatorApplication.java
new file mode 100755 (executable)
index 0000000..bb1b190
--- /dev/null
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.cache.annotation.EnableCaching;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@EnableCaching
+@SpringBootApplication(scanBasePackages = {"org.onap"})
+public class AaiSimulatorApplication extends SpringBootServletInitializer {
+    
+    public static void main(final String[] args) {
+        SpringApplication.run(AaiSimulatorApplication.class, args);
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/configration/ApplicationConfigration.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/configration/ApplicationConfigration.java
new file mode 100755 (executable)
index 0000000..109be8a
--- /dev/null
@@ -0,0 +1,109 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.configration;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.net.ssl.SSLContext;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.onap.so.aaisimulator.utils.CacheName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.concurrent.ConcurrentMapCache;
+import org.springframework.cache.support.SimpleCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.io.Resource;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Configuration
+public class ApplicationConfigration {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfigration.class);
+
+
+    @Bean
+    public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
+        return (mapperBuilder) -> mapperBuilder.modulesToInstall(new JaxbAnnotationModule());
+    }
+
+    @Bean
+    public CacheManager cacheManager() {
+        final SimpleCacheManager manager = new SimpleCacheManager();
+
+        final List<Cache> caches = new ArrayList<>();
+        for (final CacheName cacheName : CacheName.values()) {
+            caches.add(getCache(cacheName.getName()));
+        }
+        manager.setCaches(caches);
+        return manager;
+    }
+
+    private Cache getCache(final String name) {
+        LOGGER.info("Creating cache with name: {}", name);
+        return new ConcurrentMapCache(name);
+    }
+
+    @Profile("!test")
+    @Bean
+    public RestTemplate restTemplate(@Value("${http.client.ssl.trust-store:#{null}}") final Resource trustStore,
+            @Value("${http.client.ssl.trust-store-password:#{null}}") final String trustStorePassword)
+            throws Exception {
+        LOGGER.info("Setting up RestTemplate .... ");
+        final RestTemplate restTemplate = new RestTemplate();
+
+        final HttpComponentsClientHttpRequestFactory factory =
+                new HttpComponentsClientHttpRequestFactory(httpClient(trustStore, trustStorePassword));
+
+        restTemplate.setRequestFactory(factory);
+        return restTemplate;
+    }
+
+    private CloseableHttpClient httpClient(final Resource trustStore, final String trustStorePassword)
+            throws Exception {
+        LOGGER.info("Creating SSLConnectionSocketFactory with custom SSLContext and HostnameVerifier ... ");
+        return HttpClients.custom().setSSLSocketFactory(getSSLConnectionSocketFactory(trustStore, trustStorePassword))
+                .build();
+    }
+
+    private SSLConnectionSocketFactory getSSLConnectionSocketFactory(final Resource trustStore,
+            final String trustStorePassword) throws Exception {
+        return new SSLConnectionSocketFactory(getSslContext(trustStore, trustStorePassword));
+    }
+
+    private SSLContext getSslContext(final Resource trustStore, final String trustStorePassword)
+            throws Exception, Exception {
+        return new SSLContextBuilder().loadTrustMaterial(trustStore.getURL(), trustStorePassword.toCharArray()).build();
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/configration/WebSecurityConfigImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/configration/WebSecurityConfigImpl.java
new file mode 100755 (executable)
index 0000000..1dc483f
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.configration;
+
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.simulator.configuration.SimulatorSecurityConfigurer;
+import org.onap.so.simulator.model.UserCredentials;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfigImpl extends SimulatorSecurityConfigurer {
+
+    @Autowired
+    public WebSecurityConfigImpl(final UserCredentials userCredentials) {
+        super(userCredentials.getUsers());
+    }
+
+    @Override
+    protected void configure(final HttpSecurity http) throws Exception {
+        http.csrf().disable().authorizeRequests().antMatchers(Constants.BUSINESS_URL + "/**/**").authenticated().and()
+                .httpBasic();
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/AaiSimulatorController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/AaiSimulatorController.java
new file mode 100755 (executable)
index 0000000..f591290
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.HEALTHY;
+import javax.ws.rs.core.MediaType;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Controller
+@RequestMapping(path = Constants.BASE_URL)
+public class AaiSimulatorController {
+    private static final Logger LOGGER = LoggerFactory.getLogger(AaiSimulatorController.class);
+
+    @ResponseBody
+    @GetMapping(value = "/healthcheck", produces = MediaType.TEXT_PLAIN)
+    @ResponseStatus(code = HttpStatus.OK)
+    public String healthCheck() {
+        LOGGER.info("Running health check ...");
+        return HEALTHY;
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/BusinessController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/BusinessController.java
new file mode 100755 (executable)
index 0000000..4a0ed1b
--- /dev/null
@@ -0,0 +1,356 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.CUSTOMER_TYPE;
+import static org.onap.so.aaisimulator.utils.Constants.CUSTOMER_URL;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF_VNF_ID;
+import static org.onap.so.aaisimulator.utils.Constants.SERVICE_RESOURCE_TYPE;
+import static org.onap.so.aaisimulator.utils.Constants.SERVICE_SUBSCRIPTION;
+import static org.onap.so.aaisimulator.utils.Constants.X_HTTP_METHOD_OVERRIDE;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.Customer;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.GenericVnfs;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.aai.domain.yang.ServiceInstances;
+import org.onap.aai.domain.yang.ServiceSubscription;
+import org.onap.so.aaisimulator.models.NodeServiceInstance;
+import org.onap.so.aaisimulator.service.providers.CustomerCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.GenericVnfCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.NodesCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+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.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Controller
+@RequestMapping(path = CUSTOMER_URL)
+public class BusinessController {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(BusinessController.class);
+    private final CustomerCacheServiceProvider cacheServiceProvider;
+    private final NodesCacheServiceProvider nodesCacheServiceProvider;
+    private final GenericVnfCacheServiceProvider genericVnfCacheServiceProvider;
+
+    @Autowired
+    public BusinessController(final CustomerCacheServiceProvider cacheServiceProvider,
+            final NodesCacheServiceProvider nodesCacheServiceProvider,
+            final GenericVnfCacheServiceProvider genericVnfCacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+        this.nodesCacheServiceProvider = nodesCacheServiceProvider;
+        this.genericVnfCacheServiceProvider = genericVnfCacheServiceProvider;
+    }
+
+    @GetMapping(value = "{global-customer-id}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getCustomer(@PathVariable("global-customer-id") final String globalCustomerId,
+            final HttpServletRequest request) {
+        LOGGER.info("Will retrieve customer for 'global customer id': {} ...", globalCustomerId);
+
+        final Optional<Customer> optional = cacheServiceProvider.getCustomer(globalCustomerId);
+        if (optional.isPresent()) {
+            final Customer customer = optional.get();
+            LOGGER.info("found customer {} in cache", customer);
+            return ResponseEntity.ok(customer);
+        }
+
+        LOGGER.error("Couldn't find {} in cache", globalCustomerId);
+        return getRequestErrorResponseEntity(request, CUSTOMER_TYPE);
+    }
+
+    @PutMapping(value = "/{global-customer-id}", consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putCustomer(@RequestBody final Customer customer,
+            @PathVariable("global-customer-id") final String globalCustomerId, final HttpServletRequest request) {
+        LOGGER.info("Will put customer for 'global customer id': {} ...", globalCustomerId);
+
+        if (customer.getResourceVersion() == null || customer.getResourceVersion().isEmpty()) {
+            customer.setResourceVersion(getResourceVersion());
+
+        }
+        cacheServiceProvider.putCustomer(globalCustomerId, customer);
+        return ResponseEntity.accepted().build();
+
+    }
+
+    @GetMapping(value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getCustomer(@PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType, final HttpServletRequest request) {
+        LOGGER.info("Will retrieve service subscription for 'global customer id': {} and 'service type': {} ...",
+                globalCustomerId, serviceType);
+
+        final Optional<ServiceSubscription> optional =
+                cacheServiceProvider.getServiceSubscription(globalCustomerId, serviceType);
+        if (optional.isPresent()) {
+            final ServiceSubscription serviceSubscription = optional.get();
+            LOGGER.info("found service subscription  {} in cache", serviceSubscription);
+            return ResponseEntity.ok(serviceSubscription);
+        }
+
+        LOGGER.error("Couldn't find 'global customer id': {} and 'service type': {} in cache", globalCustomerId,
+                serviceType);
+        return getRequestErrorResponseEntity(request, SERVICE_SUBSCRIPTION);
+    }
+
+    @PutMapping(value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putServiceSubscription(@PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType,
+            @RequestBody final ServiceSubscription serviceSubscription, final HttpServletRequest request) {
+        LOGGER.info("Will add service subscription for 'global customer id': {} and 'service type': {} ...",
+                globalCustomerId, serviceType);
+
+        if (cacheServiceProvider.putServiceSubscription(globalCustomerId, serviceType, serviceSubscription)) {
+            LOGGER.info("Successfully add service subscription in cache ...");
+            return ResponseEntity.accepted().build();
+        }
+
+        LOGGER.error("Couldn't add service subscription using 'global customer id': {} and 'service type': {}",
+                globalCustomerId, serviceType);
+        return getRequestErrorResponseEntity(request, SERVICE_SUBSCRIPTION);
+    }
+
+    @GetMapping(
+            value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getSericeInstances(@PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType,
+            @RequestParam(name = "service-instance-name") final String serviceInstanceName,
+            @RequestParam(name = "depth", required = false) final Integer depth, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "Will retrieve service instances for 'global customer id': {}, 'service type': {} and 'service instance name: '{} with depth: {}...",
+                globalCustomerId, serviceType, serviceInstanceName, depth);
+
+        final Optional<ServiceInstances> optional =
+                cacheServiceProvider.getServiceInstances(globalCustomerId, serviceType, serviceInstanceName);
+        if (optional.isPresent()) {
+            final ServiceInstances serviceInstances = optional.get();
+            LOGGER.info("found service instance  {} in cache", serviceInstances);
+            return ResponseEntity.ok(serviceInstances);
+        }
+        LOGGER.error(
+                "Couldn't find 'global customer id': {}, 'service type': {} and 'service instance name': {} with depth: {} in cache",
+                globalCustomerId, serviceType, serviceInstanceName, depth);
+        return getRequestErrorResponseEntity(request);
+    }
+
+    @GetMapping(
+            value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getSericeInstance(@PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType,
+            @PathVariable(name = "service-instance-id") final String serviceInstanceId,
+            @RequestParam(name = "depth", required = false) final Integer depth,
+            @RequestParam(name = "resultIndex", required = false) final Integer resultIndex,
+            @RequestParam(name = "resultSize", required = false) final Integer resultSize,
+            @RequestParam(name = "format", required = false) final String format, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "Will retrieve service instances for 'global customer id': {}, 'service type': {} and 'service instance id: '{} with depth: {}, resultIndex:{}, resultSize: {} and format: {}...",
+                globalCustomerId, serviceType, serviceInstanceId, depth, resultIndex, resultSize, format);
+
+        final Optional<ServiceInstance> optional =
+                cacheServiceProvider.getServiceInstance(globalCustomerId, serviceType, serviceInstanceId);
+        if (optional.isPresent()) {
+            final ServiceInstance serviceInstance = optional.get();
+            LOGGER.info("found service instance  {} in cache", serviceInstance);
+            return ResponseEntity.ok(serviceInstance);
+        }
+        LOGGER.error(
+                "Couldn't find 'global customer id': {}, 'service type': {} and 'service instance id': {} with depth: {}, resultIndex:{}, resultSize: {} and format: {} in cache",
+                globalCustomerId, serviceType, serviceInstanceId, depth, resultIndex, resultSize, format);
+        return getRequestErrorResponseEntity(request);
+    }
+
+    @PutMapping(
+            value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putSericeInstance(@PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType,
+            @PathVariable(name = "service-instance-id") final String serviceInstanceId,
+            @RequestHeader(value = X_HTTP_METHOD_OVERRIDE, required = false) final String invocationId,
+            @RequestBody final ServiceInstance serviceInstance, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "Will add service instance for 'global customer id': {}, 'service type': {} and 'service instance id: '{} ...",
+                globalCustomerId, serviceType, serviceInstanceId);
+
+        if (serviceInstance.getResourceVersion() == null || serviceInstance.getResourceVersion().isEmpty()) {
+            serviceInstance.setResourceVersion(getResourceVersion());
+        }
+
+        if (cacheServiceProvider.putServiceInstance(globalCustomerId, serviceType, serviceInstanceId,
+                serviceInstance)) {
+            nodesCacheServiceProvider.putNodeServiceInstance(serviceInstanceId, new NodeServiceInstance(
+                    globalCustomerId, serviceType, serviceInstanceId, SERVICE_RESOURCE_TYPE, request.getRequestURI()));
+            return ResponseEntity.accepted().build();
+        }
+
+        LOGGER.error("Couldn't add 'global customer id': {}, 'service type': {} and 'service instance id': {} to cache",
+                globalCustomerId, serviceType, serviceInstanceId);
+        return getRequestErrorResponseEntity(request);
+    }
+
+    @PostMapping(
+            value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> patchSericeInstance(@PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType,
+            @PathVariable(name = "service-instance-id") final String serviceInstanceId,
+            @RequestHeader(value = X_HTTP_METHOD_OVERRIDE, required = false) final String xHttpHeaderOverride,
+            @RequestBody final ServiceInstance serviceInstance, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "Will post service instance for 'global customer id': {}, 'service type': {}, 'service instance id: '{} and '{}': {}...",
+                globalCustomerId, serviceType, serviceInstanceId, X_HTTP_METHOD_OVERRIDE, xHttpHeaderOverride);
+
+        if (HttpMethod.PATCH.toString().equalsIgnoreCase(xHttpHeaderOverride)) {
+            cacheServiceProvider.patchServiceInstance(globalCustomerId, serviceType, serviceInstanceId,
+                    serviceInstance);
+            return ResponseEntity.accepted().build();
+        }
+        LOGGER.error("{} not supported ... ", xHttpHeaderOverride);
+
+        return getRequestErrorResponseEntity(request);
+    }
+
+
+    @GetMapping(
+            value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}/related-to/generic-vnfs",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getRelatedToGenericVnf(@PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType,
+            @PathVariable(name = "service-instance-id") final String serviceInstanceId,
+            @RequestParam(name = "vnf-name", required = true) final String vnfName, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "Will retrieve generic vnf related to information for 'global customer id': {}, 'service type': {} and 'service instance id: '{} with vnfname: {}...",
+                globalCustomerId, serviceType, serviceInstanceId, vnfName);
+
+        final Optional<Relationship> optional =
+                cacheServiceProvider.getRelationship(globalCustomerId, serviceType, serviceInstanceId, vnfName);
+
+        if (optional.isPresent()) {
+
+            final Relationship relationship = optional.get();
+            final Optional<RelationshipData> relationshipDataOptional = relationship.getRelationshipData().stream()
+                    .filter(existing -> GENERIC_VNF_VNF_ID.equals(existing.getRelationshipKey())).findFirst();
+
+            if (relationshipDataOptional.isPresent()) {
+                final RelationshipData relationshipData = relationshipDataOptional.get();
+                final String vnfId = relationshipData.getRelationshipValue();
+                final Optional<GenericVnf> genericVnfOptional = genericVnfCacheServiceProvider.getGenericVnf(vnfId);
+                if (genericVnfOptional.isPresent()) {
+                    final GenericVnfs genericVnfs = new GenericVnfs();
+                    genericVnfs.getGenericVnf().add(genericVnfOptional.get());
+                    LOGGER.info("found service instance  {} in cache", relationship);
+                    return ResponseEntity.ok(genericVnfs);
+                }
+            }
+        }
+        LOGGER.error(
+                "Couldn't find  generic vnf related to information for 'global customer id': {}, 'service type': {} and 'service instance id: '{} with vnfname: {}...",
+                globalCustomerId, serviceType, serviceInstanceId, vnfName);
+        return getRequestErrorResponseEntity(request, GENERIC_VNF);
+    }
+
+    @PutMapping(
+            value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}"
+                    + BI_DIRECTIONAL_RELATIONSHIP_LIST_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putSericeInstanceRelationShip(
+            @PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType,
+            @PathVariable(name = "service-instance-id") final String serviceInstanceId,
+            @RequestBody final Relationship relationship, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "Will add {} relationship for 'global customer id': {}, 'service type': {} and 'service instance id: '{} ...",
+                relationship.getRelatedTo(), globalCustomerId, serviceType, serviceInstanceId);
+        final Optional<Relationship> optional = cacheServiceProvider.addRelationShip(globalCustomerId, serviceType,
+                serviceInstanceId, relationship, request.getRequestURI());
+
+        if (optional.isPresent()) {
+            final Relationship resultantRelationship = optional.get();
+            LOGGER.info("Relationship add, sending resultant relationship: {} in response ...", resultantRelationship);
+            return ResponseEntity.accepted().body(resultantRelationship);
+        }
+
+        LOGGER.error(
+                "Couldn't add {} relationship for 'global customer id': {}, 'service type': {} and 'service instance id: '{} ...",
+                relationship.getRelatedTo(), globalCustomerId, serviceType, serviceInstanceId);
+
+        return getRequestErrorResponseEntity(request);
+    }
+
+    @DeleteMapping(
+            value = "/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> deleteSericeInstance(@PathVariable("global-customer-id") final String globalCustomerId,
+            @PathVariable("service-type") final String serviceType,
+            @PathVariable(name = "service-instance-id") final String serviceInstanceId,
+            @RequestParam(name = "resource-version") final String resourceVersion, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "Will delete SericeInstance for 'global-customer-id': {}, 'service-type': {}, 'service-instance-id': {} and 'resource-version': {}",
+                globalCustomerId, serviceType, serviceInstanceId, resourceVersion);
+
+        if (cacheServiceProvider.deleteSericeInstance(globalCustomerId, serviceType, serviceInstanceId,
+                resourceVersion)) {
+            LOGGER.info(
+                    "Successfully deleted SericeInstance from cache for 'global-customer-id': {}, 'service-type': {}, 'service-instance-id': {} and 'resource-version': {}",
+                    globalCustomerId, serviceType, serviceInstanceId, resourceVersion);
+            return ResponseEntity.noContent().build();
+        }
+
+        LOGGER.error(
+                "Unable to delete SericeInstance from cache for 'global-customer-id': {}, 'service-type': {}, 'service-instance-id': {} and 'resource-version': {}",
+                globalCustomerId, serviceType, serviceInstanceId, resourceVersion);
+
+        return getRequestErrorResponseEntity(request);
+
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/CloudRegionsController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/CloudRegionsController.java
new file mode 100755 (executable)
index 0000000..8e007de
--- /dev/null
@@ -0,0 +1,396 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.CLOUD_REGION;
+import static org.onap.so.aaisimulator.utils.Constants.CLOUD_REGIONS;
+import static org.onap.so.aaisimulator.utils.Constants.ESR_SYSTEM_INFO_LIST;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.Constants.VSERVER;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getHeaders;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.CloudRegion;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrSystemInfoList;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.Tenant;
+import org.onap.aai.domain.yang.Vserver;
+import org.onap.so.aaisimulator.models.CloudRegionKey;
+import org.onap.so.aaisimulator.service.providers.CloudRegionCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.HttpServiceUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+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.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Controller
+@RequestMapping(path = CLOUD_REGIONS)
+public class CloudRegionsController {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CloudRegionsController.class);
+
+    private final CloudRegionCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    public CloudRegionsController(final CloudRegionCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @PutMapping(value = "{cloud-owner}/{cloud-region-id}",
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putCloudRegion(@RequestBody final CloudRegion cloudRegion,
+            @PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId, final HttpServletRequest request) {
+
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+
+        if (key.isValid()) {
+            LOGGER.info("Will add CloudRegion to cache with key 'key': {} ....", key);
+            if (cloudRegion.getResourceVersion() == null || cloudRegion.getResourceVersion().isEmpty()) {
+                cloudRegion.setResourceVersion(getResourceVersion());
+            }
+            cacheServiceProvider.putCloudRegion(key, cloudRegion);
+            return ResponseEntity.accepted().build();
+        }
+
+        LOGGER.error("Unable to add CloudRegion in cache because of invalid key {}", key);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+    @GetMapping(value = "{cloud-owner}/{cloud-region-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getCloudRegion(@PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @RequestParam(name = "depth", required = false) final Integer depth, final HttpServletRequest request) {
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        LOGGER.info("Retrieving CloudRegion using key : {} with depth: {}...", key, depth);
+        if (key.isValid()) {
+            final Optional<CloudRegion> optional = cacheServiceProvider.getCloudRegion(key);
+            if (optional.isPresent()) {
+                final CloudRegion cloudRegion = optional.get();
+                LOGGER.info("found CloudRegion {} in cache", cloudRegion);
+                return ResponseEntity.ok(cloudRegion);
+            }
+        }
+        LOGGER.error("Unable to find CloudRegion in cache using {}", key);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+    @PutMapping(value = "{cloud-owner}/{cloud-region-id}" + BI_DIRECTIONAL_RELATIONSHIP_LIST_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putRelationShip(@PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId, @RequestBody final Relationship relationship,
+            final HttpServletRequest request) {
+        LOGGER.info("Will add {} relationship to : {} ...", relationship.getRelatedTo());
+
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+
+        final Optional<Relationship> optional =
+                cacheServiceProvider.addRelationShip(key, relationship, request.getRequestURI());
+
+        if (optional.isPresent()) {
+            final Relationship resultantRelationship = optional.get();
+            LOGGER.info("Relationship add, sending resultant relationship: {} in response ...", resultantRelationship);
+            return ResponseEntity.accepted().body(resultantRelationship);
+        }
+
+        LOGGER.error("Couldn't add {} relationship for 'key': {} ...", relationship.getRelatedTo(), key);
+        return getRequestErrorResponseEntity(request, VSERVER);
+
+    }
+
+    @PutMapping(value = "{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}",
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putTenant(@RequestBody final Tenant tenant,
+            @PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @PathVariable("tenant-id") final String tenantId, final HttpServletRequest request) {
+
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+
+        if (key.isValid()) {
+            LOGGER.info("Will add Tenant to cache with key 'key': {} ....", key);
+            if (tenant.getResourceVersion() == null || tenant.getResourceVersion().isEmpty()) {
+                tenant.setResourceVersion(getResourceVersion());
+            }
+            if (cacheServiceProvider.putTenant(key, tenantId, tenant)) {
+                return ResponseEntity.accepted().build();
+            }
+        }
+
+        LOGGER.error("Unable to add Tenant in cache using key {}", key);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+    @GetMapping(value = "{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getTenant(@PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @PathVariable("tenant-id") final String tenantId, final HttpServletRequest request) {
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        LOGGER.info("Retrieving Tenant using key : {} and tenant-id:{} ...", key, tenantId);
+        if (key.isValid()) {
+            final Optional<Tenant> optional = cacheServiceProvider.getTenant(key, tenantId);
+            if (optional.isPresent()) {
+                final Tenant tenant = optional.get();
+                LOGGER.info("found Tenant {} in cache", tenant);
+                return ResponseEntity.ok(tenant);
+            }
+        }
+        LOGGER.error("Unable to find Tenant in cache key : {} and tenant-id:{} ...", key, tenantId);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+    @PutMapping(
+            value = "{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}" + RELATIONSHIP_LIST_RELATIONSHIP_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putRelationShip(@RequestBody final Relationship relationship,
+            @PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @PathVariable("tenant-id") final String tenantId, final HttpServletRequest request) {
+
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        LOGGER.info("Will put RelationShip for key : {} and tenant-id:{} ...", key, tenantId);
+
+        if (relationship.getRelatedLink() != null) {
+            final String targetBaseUrl = HttpServiceUtils.getBaseUrl(request).toString();
+            final HttpHeaders incomingHeader = getHeaders(request);
+            final boolean result = cacheServiceProvider.addRelationShip(incomingHeader, targetBaseUrl,
+                    request.getRequestURI(), key, tenantId, relationship);
+            if (result) {
+                LOGGER.info("added created bi directional relationship with {}", relationship.getRelatedLink());
+                return ResponseEntity.accepted().build();
+            }
+
+        }
+        LOGGER.error("Unable to add relationship for related link: {}", relationship.getRelatedLink());
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+    @PutMapping(value = "{cloud-owner}/{cloud-region-id}/esr-system-info-list/esr-system-info/{esr-system-info-id}",
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putEsrSystemInfo(@RequestBody final EsrSystemInfo esrSystemInfo,
+            @PathVariable("esr-system-info-id") final String esrSystemInfoId,
+            @PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId, final HttpServletRequest request) {
+
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+
+        LOGGER.info("Will put esrSystemInfo for 'key': {} ...", key);
+
+        if (esrSystemInfo.getResourceVersion() == null || esrSystemInfo.getResourceVersion().isEmpty()) {
+            esrSystemInfo.setResourceVersion(getResourceVersion());
+
+        }
+
+        if (cacheServiceProvider.putEsrSystemInfo(key, esrSystemInfoId, esrSystemInfo)) {
+            LOGGER.info("Successfully added EsrSystemInfo key : {}  ...", key, esrSystemInfo);
+            return ResponseEntity.accepted().build();
+        }
+        LOGGER.error("Unable to add EsrSystemInfo in cache for key : {} ...", key);
+
+        return getRequestErrorResponseEntity(request, ESR_SYSTEM_INFO_LIST);
+    }
+
+    @GetMapping(value = "{cloud-owner}/{cloud-region-id}/esr-system-info-list",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getEsrSystemInfoList(@PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId, final HttpServletRequest request) {
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        LOGGER.info("Retrieving EsrSystemInfoList using key : {} ...", key);
+        if (key.isValid()) {
+            final Optional<EsrSystemInfoList> optional = cacheServiceProvider.getEsrSystemInfoList(key);
+            if (optional.isPresent()) {
+                final EsrSystemInfoList esrSystemInfoList = optional.get();
+                LOGGER.info("found EsrSystemInfoList {} in cache", esrSystemInfoList);
+                return ResponseEntity.ok(esrSystemInfoList);
+            }
+        }
+        LOGGER.error("Unable to find EsrSystemInfoList in cache using key : {} ...", key);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+    @PutMapping(value = "{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}",
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putVserver(@RequestBody final Vserver vServer,
+            @PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @PathVariable("tenant-id") final String tenantId, @PathVariable("vserver-id") final String vServerId,
+            final HttpServletRequest request) {
+
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        if (vServer.getResourceVersion() == null || vServer.getResourceVersion().isEmpty()) {
+            vServer.setResourceVersion(getResourceVersion());
+        }
+        LOGGER.info("Will put Vserver in cache using using key: {}, tenantId: {}, vServerId: {} ...", key, tenantId,
+                vServerId);
+
+        if (cacheServiceProvider.putVserver(key, tenantId, vServerId, vServer)) {
+
+            if (vServer.getRelationshipList() != null) {
+                for (final Relationship relationship : vServer.getRelationshipList().getRelationship()) {
+                    if (relationship.getRelatedLink() != null) {
+                        final String requestUri = request.getRequestURI();
+                        final String targetBaseUrl =
+                                HttpServiceUtils.getBaseUrl(request.getRequestURL(), requestUri).toString();
+                        final HttpHeaders incomingHeader = getHeaders(request);
+                        final boolean result = cacheServiceProvider.addVServerRelationShip(incomingHeader,
+                                targetBaseUrl, requestUri, key, tenantId, vServerId, relationship);
+                        if (!result) {
+                            LOGGER.error(
+                                    "Unable to add Vserver relationship in cache using key: {}, tenantId: {}, vServerId: {}",
+                                    key, tenantId, vServerId);
+                            return getRequestErrorResponseEntity(request, CLOUD_REGION);
+                        }
+                        LOGGER.info("Successfully added relationship with {}", relationship.getRelatedLink());
+                    }
+                }
+            }
+
+            LOGGER.info("Successfully added Vserver for key: {}, tenantId: {}, vServerId: {} ...", key, tenantId,
+                    vServerId);
+            return ResponseEntity.accepted().build();
+        }
+        LOGGER.error("Unable to add Vserver in cache using key: {}, tenantId: {}, vServerId: {}", key, tenantId,
+                vServerId);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+    @GetMapping(value = "{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getVserver(@PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @PathVariable("tenant-id") final String tenantId, @PathVariable("vserver-id") final String vServerId,
+            final HttpServletRequest request) {
+
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        LOGGER.info("Retrieving Vserver using key: {}, tenant-id: {}  and vserver-id: {}...", key, tenantId, vServerId);
+        final Optional<Vserver> optional = cacheServiceProvider.getVserver(key, tenantId, vServerId);
+        if (optional.isPresent()) {
+            final Vserver vServer = optional.get();
+            LOGGER.info("found Vserver {} in cache", vServer);
+            return ResponseEntity.ok(vServer);
+        }
+        LOGGER.error("Unable to find Vserver in cache using key: {}, tenant-id: {}  and vserver-id: {}...", key,
+                tenantId, vServerId);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+
+    @DeleteMapping(value = "{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> deleteVserver(@PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @PathVariable("tenant-id") final String tenantId, @PathVariable("vserver-id") final String vServerId,
+            @RequestParam(name = "resource-version") final String resourceVersion, final HttpServletRequest request) {
+
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        LOGGER.info("Will delete Vserver using key: {}, tenant-id: {}, vserver-id: {} and resource-version: {}...", key,
+                tenantId, vServerId, resourceVersion);
+
+
+        if (cacheServiceProvider.deleteVserver(key, tenantId, vServerId, resourceVersion)) {
+            LOGGER.info(
+                    "Successfully delete Vserver from cache for key: {}, tenant-id: {}, vserver-id: {} and resource-version: {}",
+                    key, tenantId, vServerId, resourceVersion);
+            return ResponseEntity.noContent().build();
+        }
+
+        LOGGER.error(
+                "Unable to delete Vserver from cache using key: {}, tenant-id: {}, vserver-id: {} and resource-version: {} ...",
+                key, tenantId, vServerId, resourceVersion);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+    }
+
+    @PutMapping(
+            value = "{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}"
+                    + RELATIONSHIP_LIST_RELATIONSHIP_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putVserverRelationShip(@PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @PathVariable("tenant-id") final String tenantId, @PathVariable("vserver-id") final String vServerId,
+            @RequestBody final Relationship relationship, final HttpServletRequest request) {
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        LOGGER.info("Will add {} relationship to : {} ...", relationship.getRelatedTo());
+
+        if (relationship.getRelatedLink() != null) {
+            final String targetBaseUrl = HttpServiceUtils.getBaseUrl(request).toString();
+            final HttpHeaders incomingHeader = getHeaders(request);
+            final boolean result = cacheServiceProvider.addVServerRelationShip(incomingHeader, targetBaseUrl,
+                    request.getRequestURI(), key, tenantId, vServerId, relationship);
+            if (result) {
+                LOGGER.info("added created bi directional relationship with {}", relationship.getRelatedLink());
+                return ResponseEntity.accepted().build();
+            }
+        }
+        LOGGER.error("Couldn't add {} relationship for 'key': {} ...", relationship.getRelatedTo(), key);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+
+    }
+
+    @PutMapping(
+            value = "{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}"
+                    + BI_DIRECTIONAL_RELATIONSHIP_LIST_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putBiDirectionalVServerRelationShip(@PathVariable("cloud-owner") final String cloudOwner,
+            @PathVariable("cloud-region-id") final String cloudRegionId,
+            @PathVariable("tenant-id") final String tenantId, @PathVariable("vserver-id") final String vServerId,
+            @RequestBody final Relationship relationship, final HttpServletRequest request) {
+        final CloudRegionKey key = new CloudRegionKey(cloudOwner, cloudRegionId);
+        LOGGER.info("Will add {} relationship to : {} ...", relationship.getRelatedTo());
+
+        final Optional<Relationship> optional = cacheServiceProvider.addvServerRelationShip(key, tenantId, vServerId,
+                relationship, request.getRequestURI());
+
+        if (optional.isPresent()) {
+            final Relationship resultantRelationship = optional.get();
+            LOGGER.info("Relationship add, sending resultant relationship: {} in response ...", resultantRelationship);
+            return ResponseEntity.accepted().body(resultantRelationship);
+        }
+        LOGGER.error("Couldn't add {} relationship for 'key': {} ...", relationship.getRelatedTo(), key);
+        return getRequestErrorResponseEntity(request, CLOUD_REGION);
+
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/ExternalSystemEsrController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/ExternalSystemEsrController.java
new file mode 100755 (executable)
index 0000000..297c2eb
--- /dev/null
@@ -0,0 +1,175 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.ESR_SYSTEM_INFO;
+import static org.onap.so.aaisimulator.utils.Constants.ESR_SYSTEM_INFO_LIST;
+import static org.onap.so.aaisimulator.utils.Constants.ESR_VNFM;
+import static org.onap.so.aaisimulator.utils.Constants.EXTERNAL_SYSTEM_ESR_VNFM_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getHeaders;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+import java.util.List;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrSystemInfoList;
+import org.onap.aai.domain.yang.EsrVnfm;
+import org.onap.aai.domain.yang.EsrVnfmList;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.so.aaisimulator.service.providers.ExternalSystemCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.HttpServiceUtils;
+import org.onap.so.aaisimulator.utils.RequestErrorResponseUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Controller
+@RequestMapping(path = EXTERNAL_SYSTEM_ESR_VNFM_LIST_URL)
+public class ExternalSystemEsrController {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ExternalSystemEsrController.class);
+
+    private final ExternalSystemCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    public ExternalSystemEsrController(final ExternalSystemCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @PutMapping(value = "/esr-vnfm/{vnfm-id}", consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putEsrVnfm(@RequestBody final EsrVnfm esrVnfm,
+            @PathVariable("vnfm-id") final String vnfmId, final HttpServletRequest request) {
+        LOGGER.info("Will put esr-vnfm to cache for 'vnfm id': {} ...", esrVnfm.getVnfmId());
+
+        if (esrVnfm.getResourceVersion() == null || esrVnfm.getResourceVersion().isEmpty()) {
+            esrVnfm.setResourceVersion(getResourceVersion());
+
+        }
+        cacheServiceProvider.putEsrVnfm(vnfmId, esrVnfm);
+        return ResponseEntity.accepted().build();
+    }
+
+    @GetMapping(value = "/esr-vnfm/{vnfm-id}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getEsrVnfm(@PathVariable("vnfm-id") final String vnfmId,
+            @RequestParam(name = "depth", required = false) final Integer depth, final HttpServletRequest request) {
+        LOGGER.info("Will retrieve ESR VNFM for 'vnfm id': {} with depth: {}...", vnfmId, depth);
+
+        final Optional<EsrVnfm> optional = cacheServiceProvider.getEsrVnfm(vnfmId);
+        if (optional.isPresent()) {
+            final EsrVnfm esrVnfm = optional.get();
+            LOGGER.info("found esrVnfm {} in cache", esrVnfm);
+            return ResponseEntity.ok(esrVnfm);
+        }
+
+        LOGGER.error("Couldn't Esr Vnfm for 'vnfm id': {} with depth: {}...", vnfmId, depth);
+        return getRequestErrorResponseEntity(request, ESR_VNFM);
+    }
+
+    @GetMapping(produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getEsrVnfmList(final HttpServletRequest request) {
+        LOGGER.info("Will retrieve a list of all ESR VNFMs");
+
+        final List<EsrVnfm> esrVnfms = cacheServiceProvider.getAllEsrVnfm();
+        LOGGER.info("found {} Esr Vnfms in cache", esrVnfms.size());
+
+        final EsrVnfmList esrVnfmList = new EsrVnfmList();
+        esrVnfmList.getEsrVnfm().addAll(esrVnfms);
+
+        return ResponseEntity.ok(esrVnfmList);
+    }
+
+    @PutMapping(value = "/esr-vnfm/{vnfm-id}/esr-system-info-list/esr-system-info/{esr-system-info-id}",
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putEsrSystemInfo(@RequestBody final EsrSystemInfo esrSystemInfo,
+            @PathVariable("vnfm-id") final String vnfmId,
+            @PathVariable("esr-system-info-id") final String esrSystemInfoId, final HttpServletRequest request) {
+        LOGGER.info("Will put esrSystemInfo for 'vnfm id': {} and 'esr-system-info-id': {} ...", vnfmId, esrSystemInfo);
+
+        if (esrSystemInfo.getResourceVersion() == null || esrSystemInfo.getResourceVersion().isEmpty()) {
+            esrSystemInfo.setResourceVersion(getResourceVersion());
+
+        }
+
+        if (cacheServiceProvider.putEsrSystemInfo(vnfmId, esrSystemInfoId, esrSystemInfo)) {
+            LOGGER.info("Successfully added EsrSystemInfo for 'vnfm id': {} and 'esr-system-info-id': {} ...", vnfmId,
+                    esrSystemInfo);
+            return ResponseEntity.accepted().build();
+        }
+        LOGGER.error("Unable to add esrSystemInfo for 'vnfm id': {} and 'esr-system-info-id': {} ...", vnfmId,
+                esrSystemInfo);
+        return getRequestErrorResponseEntity(request, ESR_SYSTEM_INFO_LIST);
+    }
+
+    @GetMapping(value = "/esr-vnfm/{vnfm-id}/esr-system-info-list",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getEsrSystemInfoList(@PathVariable("vnfm-id") final String vnfmId,
+            final HttpServletRequest request) {
+        LOGGER.info("Will retrieve esrSystemInfoList for 'vnfm id': {} ...", vnfmId);
+
+        final Optional<EsrSystemInfoList> optional = cacheServiceProvider.getEsrSystemInfoList(vnfmId);
+        if (optional.isPresent()) {
+            final EsrSystemInfoList esrSystemInfoList = optional.get();
+            LOGGER.info("found esrSystemInfoList {} in cache", esrSystemInfoList);
+            return ResponseEntity.ok(esrSystemInfoList);
+        }
+
+        LOGGER.error("Couldn't find esrSystemInfoList for 'vnfm id': {} ...", vnfmId);
+        return getRequestErrorResponseEntity(request, ESR_SYSTEM_INFO);
+    }
+
+    @PutMapping(value = "/esr-vnfm/{vnfm-id}" + RELATIONSHIP_LIST_RELATIONSHIP_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putEsrVnfmRelationShip(@RequestBody final Relationship relationship,
+            @PathVariable("vnfm-id") final String vnfmId, final HttpServletRequest request) {
+        LOGGER.info("Will put RelationShip for 'vnfm-id': {} ...", vnfmId);
+
+        if (relationship.getRelatedLink() != null) {
+            final String targetBaseUrl = HttpServiceUtils.getBaseUrl(request).toString();
+            final HttpHeaders incomingHeader = getHeaders(request);
+            final boolean result = cacheServiceProvider.addRelationShip(incomingHeader, targetBaseUrl,
+                    request.getRequestURI(), vnfmId, relationship);
+            if (result) {
+                LOGGER.info("added created bi directional relationship with {}", relationship.getRelatedLink());
+                return ResponseEntity.accepted().build();
+            }
+        }
+        LOGGER.error("Unable to add relationship for related link: {}", relationship.getRelatedLink());
+        return RequestErrorResponseUtils.getRequestErrorResponseEntity(request, ESR_VNFM);
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/GenericVnfsController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/GenericVnfsController.java
new file mode 100755 (executable)
index 0000000..43fe47d
--- /dev/null
@@ -0,0 +1,215 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.APPLICATION_MERGE_PATCH_JSON;
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNFS_URL;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.Constants.X_HTTP_METHOD_OVERRIDE;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getHeaders;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+import java.util.List;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.GenericVnfs;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.so.aaisimulator.service.providers.GenericVnfCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.HttpServiceUtils;
+import org.onap.so.aaisimulator.utils.RequestErrorResponseUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+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.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Controller
+@RequestMapping(path = GENERIC_VNFS_URL)
+public class GenericVnfsController {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(GenericVnfsController.class);
+
+    private final GenericVnfCacheServiceProvider cacheServiceProvider;
+
+
+    @Autowired
+    public GenericVnfsController(final GenericVnfCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @PutMapping(value = "/generic-vnf/{vnf-id}", consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putGenericVnf(@RequestBody final GenericVnf genericVnf,
+            @PathVariable("vnf-id") final String vnfId, final HttpServletRequest request) {
+        LOGGER.info("Will add GenericVnf to cache with 'vnf-id': {} ...", vnfId);
+
+        if (genericVnf.getResourceVersion() == null || genericVnf.getResourceVersion().isEmpty()) {
+            genericVnf.setResourceVersion(getResourceVersion());
+
+        }
+        cacheServiceProvider.putGenericVnf(vnfId, genericVnf);
+        return ResponseEntity.accepted().build();
+
+    }
+
+    @GetMapping(value = "/generic-vnf/{vnf-id}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getGenericVnf(@PathVariable("vnf-id") final String vnfId,
+            @RequestParam(name = "depth", required = false) final Integer depth,
+            @RequestParam(name = "resultIndex", required = false) final Integer resultIndex,
+            @RequestParam(name = "resultSize", required = false) final Integer resultSize,
+            @RequestParam(name = "format", required = false) final String format, final HttpServletRequest request) {
+        LOGGER.info(
+                "Will get GenericVnf for 'vnf-id': {} with depth: {}, resultIndex: {}, resultSize:{}, format: {} ...",
+                vnfId, depth, resultIndex, resultSize, format);
+
+        final Optional<GenericVnf> optional = cacheServiceProvider.getGenericVnf(vnfId);
+
+        if (optional.isPresent()) {
+            final GenericVnf genericVnf = optional.get();
+            LOGGER.info("found GenericVnf {} in cache", genericVnf);
+            return ResponseEntity.ok(genericVnf);
+        }
+
+        LOGGER.error(
+                "Unable to find GenericVnf in cache for 'vnf-id': {} with depth: {}, resultIndex: {}, resultSize:{}, format:{} ...",
+                vnfId, depth, resultIndex, resultSize, format);
+        return getRequestErrorResponseEntity(request, GENERIC_VNF);
+
+    }
+
+    @PutMapping(value = "/generic-vnf/{vnf-id}" + RELATIONSHIP_LIST_RELATIONSHIP_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putGenericVnfRelationShip(@RequestBody final Relationship relationship,
+            @PathVariable("vnf-id") final String vnfId, final HttpServletRequest request) {
+        LOGGER.info("Will put RelationShip for 'vnf-id': {} ...", vnfId);
+
+        if (relationship.getRelatedLink() != null) {
+            final String targetBaseUrl = HttpServiceUtils.getBaseUrl(request).toString();
+            final HttpHeaders incomingHeader = getHeaders(request);
+            final boolean result = cacheServiceProvider.addRelationShip(incomingHeader, targetBaseUrl,
+                    request.getRequestURI(), vnfId, relationship);
+            if (result) {
+                LOGGER.info("added created bi directional relationship with {}", relationship.getRelatedLink());
+                return ResponseEntity.accepted().build();
+            }
+        }
+        LOGGER.error("Unable to add relationship for related link: {}", relationship.getRelatedLink());
+        return RequestErrorResponseUtils.getRequestErrorResponseEntity(request, GENERIC_VNF);
+    }
+
+    @PutMapping(value = "/generic-vnf/{vnf-id}" + BI_DIRECTIONAL_RELATIONSHIP_LIST_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putBiDirectionalRelationShip(@RequestBody final Relationship relationship,
+            @PathVariable("vnf-id") final String vnfId, final HttpServletRequest request) {
+        LOGGER.info("Will put RelationShip for 'vnf-id': {} ...", vnfId);
+
+        final Optional<Relationship> optional =
+                cacheServiceProvider.addRelationShip(vnfId, relationship, request.getRequestURI());
+
+        if (optional.isPresent()) {
+            final Relationship resultantRelationship = optional.get();
+            LOGGER.info("Relationship add, sending resultant relationship: {} in response ...", resultantRelationship);
+            return ResponseEntity.accepted().body(resultantRelationship);
+        }
+
+        LOGGER.error("Unable to add relationship for related link: {}", relationship.getRelatedLink());
+        return RequestErrorResponseUtils.getRequestErrorResponseEntity(request, GENERIC_VNF);
+    }
+
+    @PostMapping(value = "/generic-vnf/{vnf-id}",
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, APPLICATION_MERGE_PATCH_JSON},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> patchGenericVnf(@RequestBody final GenericVnf genericVnf,
+            @PathVariable("vnf-id") final String vnfId,
+            @RequestHeader(value = X_HTTP_METHOD_OVERRIDE, required = false) final String xHttpHeaderOverride,
+            final HttpServletRequest request) {
+
+        LOGGER.info("Will post GenericVnf to cache with 'vnf-id': {} and '{}': {} ...", vnfId, X_HTTP_METHOD_OVERRIDE,
+                xHttpHeaderOverride);
+
+        if (HttpMethod.PATCH.toString().equalsIgnoreCase(xHttpHeaderOverride)) {
+            if (cacheServiceProvider.patchGenericVnf(vnfId, genericVnf)) {
+                return ResponseEntity.accepted().build();
+            }
+            LOGGER.error("Unable to apply patch to GenericVnf using 'vnf-id': {} ... ", vnfId);
+            return getRequestErrorResponseEntity(request, GENERIC_VNF);
+        }
+        LOGGER.error("{} not supported ... ", xHttpHeaderOverride);
+
+        return getRequestErrorResponseEntity(request, GENERIC_VNF);
+    }
+
+    @GetMapping(produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getGenericVnfs(@RequestParam(name = "selflink") final String selflink,
+            final HttpServletRequest request) {
+        LOGGER.info("will retrieve GenericVnfs using selflink: {}", selflink);
+
+        final List<GenericVnf> genericVnfList = cacheServiceProvider.getGenericVnfs(selflink);
+
+        if (genericVnfList.isEmpty()) {
+            LOGGER.error("No matching generic vnfs found using selflink: {}", selflink);
+            return getRequestErrorResponseEntity(request, GENERIC_VNF);
+        }
+
+        LOGGER.info("found {} GenericVnfs in cache", genericVnfList.size());
+        final GenericVnfs genericVnfs = new GenericVnfs();
+        genericVnfs.getGenericVnf().addAll(genericVnfList);
+        return ResponseEntity.ok(genericVnfs);
+    }
+
+    @DeleteMapping(value = "/generic-vnf/{vnf-id}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> deleteGenericVnf(@PathVariable("vnf-id") final String vnfId,
+            @RequestParam(name = "resource-version") final String resourceVersion, final HttpServletRequest request) {
+        LOGGER.info("Will delete GenericVnf for 'vnf-id': {} and 'resource-version': {}", vnfId, resourceVersion);
+
+        if (cacheServiceProvider.deleteGenericVnf(vnfId, resourceVersion)) {
+            LOGGER.info("Successfully delete GenericVnf from cache for 'vnf-id': {} and 'resource-version': {}", vnfId,
+                    resourceVersion);
+            return ResponseEntity.noContent().build();
+        }
+
+        LOGGER.error("Unable to delete GenericVnf for 'vnf-id': {} and 'resource-version': {} ...", vnfId,
+                resourceVersion);
+        return getRequestErrorResponseEntity(request, GENERIC_VNF);
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/LinesOfBusinessController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/LinesOfBusinessController.java
new file mode 100755 (executable)
index 0000000..b3438d2
--- /dev/null
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.LINES_OF_BUSINESS_URL;
+import static org.onap.so.aaisimulator.utils.Constants.LINE_OF_BUSINESS;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.LineOfBusiness;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.LinesOfBusinessCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Controller
+@RequestMapping(path = LINES_OF_BUSINESS_URL)
+public class LinesOfBusinessController {
+    private static final Logger LOGGER = LoggerFactory.getLogger(LinesOfBusinessController.class);
+
+    private final LinesOfBusinessCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    public LinesOfBusinessController(final LinesOfBusinessCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @PutMapping(value = "{line-of-business-name}", consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putLineOfBusiness(@RequestBody final LineOfBusiness lineOfBusiness,
+            @PathVariable("line-of-business-name") final String lineOfBusinessName, final HttpServletRequest request) {
+
+        LOGGER.info("Will add LineOfBusiness to cache with key 'line-of-business-name': {} ...",
+                lineOfBusiness.getLineOfBusinessName());
+
+        if (lineOfBusiness.getResourceVersion() == null || lineOfBusiness.getResourceVersion().isEmpty()) {
+            lineOfBusiness.setResourceVersion(getResourceVersion());
+
+        }
+        cacheServiceProvider.putLineOfBusiness(lineOfBusinessName, lineOfBusiness);
+        return ResponseEntity.accepted().build();
+    }
+
+
+    @GetMapping(value = "{line-of-business-name}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getLineOfBusiness(@PathVariable("line-of-business-name") final String lineOfBusinessName,
+            @RequestParam(name = "depth", required = false) final Integer depth,
+            @RequestParam(name = "resultIndex", required = false) final Integer resultIndex,
+            @RequestParam(name = "resultSize", required = false) final Integer resultSize,
+            @RequestParam(name = "format", required = false) final String format, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "retrieving Platform for 'platform-name': {} with depth: {}, resultIndex: {}, resultSize:{}, format: {} ...",
+                lineOfBusinessName, depth, resultIndex, resultSize, format);
+
+        final Optional<LineOfBusiness> optional = cacheServiceProvider.getLineOfBusiness(lineOfBusinessName);
+        if (optional.isPresent()) {
+
+            final Format value = Format.forValue(format);
+            switch (value) {
+                case RAW:
+                    final LineOfBusiness platform = optional.get();
+                    LOGGER.info("found LineOfBusiness {} in cache", platform);
+                    return ResponseEntity.ok(platform);
+                case COUNT:
+                    final Map<String, Object> map = new HashMap<>();
+                    map.put(LINE_OF_BUSINESS, 1);
+                    return ResponseEntity.ok(new Results(map));
+                default:
+                    break;
+            }
+            LOGGER.error("invalid format type :{}", format);
+        }
+        LOGGER.error("Unable to find LineOfBusiness in cache using {}", lineOfBusinessName);
+        return getRequestErrorResponseEntity(request, LINE_OF_BUSINESS);
+    }
+
+    @PutMapping(value = "/{line-of-business-name}" + BI_DIRECTIONAL_RELATIONSHIP_LIST_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putRelationShip(@PathVariable("line-of-business-name") final String lineOfBusinessName,
+            @RequestBody final Relationship relationship, final HttpServletRequest request) {
+        LOGGER.info("Will add {} relationship to : {} ...", relationship.getRelatedTo());
+
+        final Optional<Relationship> optional =
+                cacheServiceProvider.addRelationShip(lineOfBusinessName, relationship, request.getRequestURI());
+
+        if (optional.isPresent()) {
+            final Relationship resultantRelationship = optional.get();
+            LOGGER.info("Relationship add, sending resultant relationship: {} in response ...", resultantRelationship);
+            return ResponseEntity.accepted().body(resultantRelationship);
+        }
+
+        LOGGER.error("Couldn't add {} relationship for 'line-of-business-name': {} ...", relationship.getRelatedTo(),
+                lineOfBusinessName);
+
+        return getRequestErrorResponseEntity(request, LINE_OF_BUSINESS);
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/NodesController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/NodesController.java
new file mode 100755 (executable)
index 0000000..21bcae9
--- /dev/null
@@ -0,0 +1,115 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF;
+import static org.onap.so.aaisimulator.utils.Constants.NODES_URL;
+import static org.onap.so.aaisimulator.utils.Constants.RESOURCE_LINK;
+import static org.onap.so.aaisimulator.utils.Constants.RESOURCE_TYPE;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.GenericVnfs;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.NodeServiceInstance;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.NodesCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Controller
+@RequestMapping(path = NODES_URL)
+public class NodesController {
+
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(NodesController.class);
+
+    private final NodesCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    public NodesController(final NodesCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @GetMapping(value = "/service-instances/service-instance/{service-instance-id}",
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getProject(@PathVariable(name = "service-instance-id") final String serviceInstanceId,
+            @RequestParam(name = "format", required = false) final String format, final HttpServletRequest request) {
+        LOGGER.info("retrieving service instance using 'service-instance-id': {} and format: {}...", serviceInstanceId,
+                format);
+
+        final Optional<NodeServiceInstance> optional = cacheServiceProvider.getNodeServiceInstance(serviceInstanceId);
+        if (!optional.isPresent()) {
+            LOGGER.error("Couldn't find {} in cache", serviceInstanceId);
+            return getRequestErrorResponseEntity(request);
+        }
+
+        final Format value = Format.forValue(format);
+        final NodeServiceInstance nodeServiceInstance = optional.get();
+        switch (value) {
+            case PATHED:
+                LOGGER.info("found project {} in cache", nodeServiceInstance);
+                final Map<String, Object> map = new LinkedHashMap<>();
+                map.put(RESOURCE_TYPE, nodeServiceInstance.getResourceType());
+                map.put(RESOURCE_LINK, nodeServiceInstance.getResourceLink());
+                return ResponseEntity.ok(new Results(map));
+            case RAW:
+                final Optional<ServiceInstance> serviceInstance =
+                        cacheServiceProvider.getServiceInstance(nodeServiceInstance);
+                if (serviceInstance.isPresent()) {
+                    return ResponseEntity.ok(serviceInstance.get());
+                }
+                LOGGER.error("Unable to find Service instance in cahce using {}", nodeServiceInstance);
+                return getRequestErrorResponseEntity(request);
+            default:
+                break;
+        }
+        LOGGER.error("invalid format type :{}", format);
+        return getRequestErrorResponseEntity(request);
+    }
+
+    @GetMapping(value = "/generic-vnfs", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getGenericVnfs(@RequestParam(name = "vnf-name") final String vnfName,
+            final HttpServletRequest request) {
+        LOGGER.info("will find GenericVnfs for name: {}", vnfName);
+        final Optional<GenericVnfs> optional = cacheServiceProvider.getGenericVnfs(vnfName);
+        if (optional.isPresent()) {
+            LOGGER.info("found matching GenericVnfs for name: {}", vnfName);
+            return ResponseEntity.ok(optional.get());
+        }
+        LOGGER.error("Unable to find GenericVnfs in cahce using {}", vnfName);
+        return getRequestErrorResponseEntity(request, GENERIC_VNF);
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/OwningEntityController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/OwningEntityController.java
new file mode 100755 (executable)
index 0000000..c5ade0c
--- /dev/null
@@ -0,0 +1,137 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.OWNING_ENTITY;
+import static org.onap.so.aaisimulator.utils.Constants.OWNING_ENTITY_URL;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getHeaders;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.OwningEntity;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.OwnEntityCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.HttpServiceUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Controller
+@RequestMapping(path = OWNING_ENTITY_URL)
+public class OwningEntityController {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(OwningEntityController.class);
+
+    private final OwnEntityCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    public OwningEntityController(final OwnEntityCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @PutMapping(value = "{owning-entity-id}", consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putOwningEntity(@RequestBody final OwningEntity owningEntity,
+            @PathVariable("owning-entity-id") final String owningEntityId, final HttpServletRequest request) {
+        LOGGER.info("Will add OwningEntity to cache with key 'owning-entity-id': {} ...",
+                owningEntity.getOwningEntityId());
+
+        if (owningEntity.getResourceVersion() == null || owningEntity.getResourceVersion().isEmpty()) {
+            owningEntity.setResourceVersion(getResourceVersion());
+
+        }
+        cacheServiceProvider.putOwningEntity(owningEntityId, owningEntity);
+        return ResponseEntity.accepted().build();
+    }
+
+    @GetMapping(value = "{owning-entity-id}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getOwningEntity(@PathVariable("owning-entity-id") final String owningEntityId,
+            @RequestParam(name = "resultIndex", required = false) final Integer resultIndex,
+            @RequestParam(name = "resultSize", required = false) final Integer resultSize,
+            @RequestParam(name = "format", required = false) final String format, final HttpServletRequest request) {
+        LOGGER.info("retrieving owning entity for 'owning-entity-id': {} ...", owningEntityId);
+
+        final Optional<OwningEntity> optional = cacheServiceProvider.getOwningEntity(owningEntityId);
+        if (!optional.isPresent()) {
+            LOGGER.error("Couldn't find {} in cache", owningEntityId);
+            return getRequestErrorResponseEntity(request);
+        }
+
+        final Format value = Format.forValue(format);
+        switch (value) {
+            case RAW:
+                final OwningEntity owningEntity = optional.get();
+                LOGGER.info("found OwningEntity {} in cache", owningEntity);
+                return ResponseEntity.ok(owningEntity);
+            case COUNT:
+                final Map<String, Object> map = new HashMap<>();
+                map.put(OWNING_ENTITY, 1);
+                return ResponseEntity.ok(new Results(map));
+            default:
+                break;
+        }
+        LOGGER.error("invalid format type :{}", format);
+        return getRequestErrorResponseEntity(request);
+    }
+
+    @PutMapping(value = "/{owning-entity-id}/relationship-list/relationship",
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putOwningEntityRelationShip(@RequestBody final Relationship relationship,
+            @PathVariable("owning-entity-id") final String owningEntityId, final HttpServletRequest request) {
+
+        LOGGER.info("adding relationship for owning-entity-id: {} ...", owningEntityId);
+
+        if (relationship.getRelatedLink() != null) {
+            final String targetBaseUrl = HttpServiceUtils.getBaseUrl(request).toString();
+            final HttpHeaders incomingHeader = getHeaders(request);
+
+            final boolean result = cacheServiceProvider.addRelationShip(incomingHeader, targetBaseUrl,
+                    request.getRequestURI(), owningEntityId, relationship);
+            if (result) {
+                LOGGER.info("added created bi directional relationship with {}", relationship.getRelatedLink());
+                return ResponseEntity.accepted().build();
+            }
+        }
+
+        LOGGER.error("Unable to add relationship for related link: {}", relationship.getRelatedLink());
+        return getRequestErrorResponseEntity(request);
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/PlatformController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/PlatformController.java
new file mode 100755 (executable)
index 0000000..39e3594
--- /dev/null
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.PLATFORM;
+import static org.onap.so.aaisimulator.utils.Constants.PLATFORMS_URL;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.Platform;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.PlatformCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Controller
+@RequestMapping(path = PLATFORMS_URL)
+public class PlatformController {
+    private static final Logger LOGGER = LoggerFactory.getLogger(PlatformController.class);
+
+    private final PlatformCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    public PlatformController(final PlatformCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @PutMapping(value = "{platform-name}", consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putPlatform(@RequestBody final Platform platform,
+            @PathVariable("platform-name") final String platformName, final HttpServletRequest request) {
+        LOGGER.info("Will add Platform to cache with key 'platform-name': {} ...", platform.getPlatformName());
+
+        if (platform.getResourceVersion() == null || platform.getResourceVersion().isEmpty()) {
+            platform.setResourceVersion(getResourceVersion());
+
+        }
+        cacheServiceProvider.putPlatform(platformName, platform);
+        return ResponseEntity.accepted().build();
+    }
+
+    @GetMapping(value = "/{platform-name}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getPlatform(@PathVariable("platform-name") final String platformName,
+            @RequestParam(name = "depth", required = false) final Integer depth,
+            @RequestParam(name = "resultIndex", required = false) final Integer resultIndex,
+            @RequestParam(name = "resultSize", required = false) final Integer resultSize,
+            @RequestParam(name = "format", required = false) final String format, final HttpServletRequest request) {
+
+        LOGGER.info(
+                "retrieving Platform for 'platform-name': {} with depth: {}, resultIndex: {}, resultSize:{}, format: {} ...",
+                platformName, depth, resultIndex, resultSize, format);
+        final Optional<Platform> optional = cacheServiceProvider.getPlatform(platformName);
+        if (optional.isPresent()) {
+
+            final Format value = Format.forValue(format);
+            switch (value) {
+                case RAW:
+                    final Platform platform = optional.get();
+                    LOGGER.info("found Platform {} in cache", platform);
+                    return ResponseEntity.ok(platform);
+                case COUNT:
+                    final Map<String, Object> map = new HashMap<>();
+                    map.put(PLATFORM, 1);
+                    return ResponseEntity.ok(new Results(map));
+                default:
+                    break;
+            }
+            LOGGER.error("invalid format type :{}", format);
+
+        }
+        LOGGER.error("Unable to find Platform in cahce using {}", platformName);
+        return getRequestErrorResponseEntity(request, PLATFORM);
+    }
+
+    @PutMapping(value = "/{platform-name}" + BI_DIRECTIONAL_RELATIONSHIP_LIST_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putRelationShip(@PathVariable("platform-name") final String platformName,
+            @RequestBody final Relationship relationship, final HttpServletRequest request) {
+        LOGGER.info("Will add {} relationship to : {} ...", relationship.getRelatedTo());
+
+        final Optional<Relationship> optional =
+                cacheServiceProvider.addRelationShip(platformName, relationship, request.getRequestURI());
+
+        if (optional.isPresent()) {
+            final Relationship resultantRelationship = optional.get();
+            LOGGER.info("Relationship add, sending resultant relationship: {} in response ...", resultantRelationship);
+            return ResponseEntity.accepted().body(resultantRelationship);
+        }
+
+        LOGGER.error("Couldn't add {} relationship for 'platform-name': {} ...", relationship.getRelatedTo(),
+                platformName);
+
+        return getRequestErrorResponseEntity(request, PLATFORM);
+
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/PnfsController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/PnfsController.java
new file mode 100755 (executable)
index 0000000..ff0e3dc
--- /dev/null
@@ -0,0 +1,159 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+
+import org.onap.aai.domain.yang.v15.Pnf;
+import org.onap.aai.domain.yang.v15.Pnfs;
+import org.onap.so.aaisimulator.service.providers.PnfCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+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.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import java.util.List;
+import java.util.Optional;
+
+import static org.onap.so.aaisimulator.utils.Constants.APPLICATION_MERGE_PATCH_JSON;
+import static org.onap.so.aaisimulator.utils.Constants.PNF;
+import static org.onap.so.aaisimulator.utils.Constants.PNFS_URL;
+import static org.onap.so.aaisimulator.utils.Constants.X_HTTP_METHOD_OVERRIDE;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+
+/**
+ * @author Raj Gumma (raj.gumma@est.tech)
+ */
+@Controller
+@RequestMapping(path = PNFS_URL)
+public class PnfsController {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PnfsController.class);
+
+    private final PnfCacheServiceProvider cacheServiceProvider;
+
+
+    @Autowired
+    public PnfsController(final PnfCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @PutMapping(value = "/pnf/{pnf-id}", consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putPnf(@RequestBody final Pnf pnf,
+                                    @PathVariable("pnf-id") final String pnfId, final HttpServletRequest request) {
+        LOGGER.info("Will add Pnf to cache with 'pnf-id': {} ...", pnfId);
+
+        if (pnf.getResourceVersion() == null || pnf.getResourceVersion().isEmpty()) {
+            pnf.setResourceVersion(getResourceVersion());
+        }
+        cacheServiceProvider.putPnf(pnfId, pnf);
+        return ResponseEntity.accepted().build();
+    }
+
+    @GetMapping(value = "/pnf/{pnf-id}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getPnf(@PathVariable("pnf-id") final String pnfId, final HttpServletRequest request) {
+        LOGGER.info("Will get Pnf for 'pnf-id': {} ", pnfId);
+
+        final Optional<Pnf> optional = cacheServiceProvider.getPnf(pnfId);
+
+        if (optional.isPresent()) {
+            final Pnf pnf = optional.get();
+            LOGGER.info("found Pnf {} in cache", pnf);
+            return ResponseEntity.ok(pnf);
+        }
+
+        LOGGER.error("Unable to find Pnf in cache for 'pnf-id': {}", pnfId);
+        return getRequestErrorResponseEntity(request, "pnf");
+
+    }
+
+    @PostMapping(value = "/pnf/{pnf-id}",
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, APPLICATION_MERGE_PATCH_JSON},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> patchPnf(@RequestBody final Pnf pnf,
+                                      @PathVariable("pnf-id") final String pnfId,
+                                      @RequestHeader(value = X_HTTP_METHOD_OVERRIDE, required = false) final String xHttpHeaderOverride,
+                                      final HttpServletRequest request) {
+
+        LOGGER.info("Will post Pnf to cache with 'pnf-id': {} and '{}': {} ...", pnfId, X_HTTP_METHOD_OVERRIDE,
+                xHttpHeaderOverride);
+
+        if (HttpMethod.PATCH.toString().equalsIgnoreCase(xHttpHeaderOverride)) {
+            if (cacheServiceProvider.patchPnf(pnfId, pnf)) {
+                return ResponseEntity.accepted().build();
+            }
+            LOGGER.error("Unable to apply patch to Pnf using 'pnf-id': {} ... ", pnfId);
+            return getRequestErrorResponseEntity(request, PNF);
+        }
+        LOGGER.error("{} not supported ... ", xHttpHeaderOverride);
+
+        return getRequestErrorResponseEntity(request, PNF);
+    }
+
+    @GetMapping(produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getPnfs(@RequestParam(name = "selflink") final String selflink,
+                                     final HttpServletRequest request) {
+        LOGGER.info("will retrieve Pnfs using selflink: {}", selflink);
+
+        final List<Pnf> pnfList = cacheServiceProvider.getPnfs(selflink);
+
+        if (pnfList.isEmpty()) {
+            LOGGER.error("No matching pnfs found using selflink: {}", selflink);
+            return getRequestErrorResponseEntity(request, PNF);
+        }
+
+        LOGGER.info("found {} Pnfs in cache", pnfList.size());
+        final Pnfs pnfs = new Pnfs();
+        pnfs.getPnf().addAll(pnfList);
+        return ResponseEntity.ok(pnfs);
+    }
+
+    @DeleteMapping(value = "/pnf/{pnf-id}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> deletePnf(@PathVariable("pnf-id") final String pnfId,
+                                       @RequestParam(name = "resource-version") final String resourceVersion, final HttpServletRequest request) {
+        LOGGER.info("Will delete Pnf for 'pnf-id': {} and 'resource-version': {}", pnfId, resourceVersion);
+
+        if (cacheServiceProvider.deletePnf(pnfId, resourceVersion)) {
+            LOGGER.info("Successfully delete Pnf from cache for 'pnf-id': {} and 'resource-version': {}", pnfId,
+                    resourceVersion);
+            return ResponseEntity.noContent().build();
+        }
+
+        LOGGER.error("Unable to delete Pnf for 'pnf-id': {} and 'resource-version': {} ...", pnfId,
+                resourceVersion);
+        return getRequestErrorResponseEntity(request, PNF);
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/ProjectController.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/ProjectController.java
new file mode 100755 (executable)
index 0000000..490982a
--- /dev/null
@@ -0,0 +1,137 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.onap.so.aaisimulator.utils.Constants.PROJECT;
+import static org.onap.so.aaisimulator.utils.Constants.PROJECT_URL;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getHeaders;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getRequestErrorResponseEntity;
+import static org.onap.so.aaisimulator.utils.RequestErrorResponseUtils.getResourceVersion;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import org.onap.aai.domain.yang.Project;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.ProjectCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.HttpServiceUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Controller
+@RequestMapping(path = PROJECT_URL)
+public class ProjectController {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ProjectController.class);
+
+    private final ProjectCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    public ProjectController(final ProjectCacheServiceProvider cacheServiceProvider) {
+        this.cacheServiceProvider = cacheServiceProvider;
+    }
+
+    @PutMapping(value = "/{project-name}", consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putProject(@RequestBody final Project project,
+            @PathVariable("project-name") final String projectName, final HttpServletRequest request) {
+        LOGGER.info("Will put project for 'project-name': {} ...", project.getProjectName());
+
+        if (project.getResourceVersion() == null || project.getResourceVersion().isEmpty()) {
+            project.setResourceVersion(getResourceVersion());
+
+        }
+        cacheServiceProvider.putProject(projectName, project);
+        return ResponseEntity.accepted().build();
+
+    }
+
+    @GetMapping(value = "/{project-name}", produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> getProject(@PathVariable("project-name") final String projectName,
+            @RequestParam(name = "resultIndex", required = false) final Integer resultIndex,
+            @RequestParam(name = "resultSize", required = false) final Integer resultSize,
+            @RequestParam(name = "format", required = false) final String format, final HttpServletRequest request) {
+        LOGGER.info("retrieving project for 'project-name': {} ...", projectName);
+
+        final Optional<Project> optional = cacheServiceProvider.getProject(projectName);
+        if (!optional.isPresent()) {
+            LOGGER.error("Couldn't find {} in cache", projectName);
+            return getRequestErrorResponseEntity(request);
+        }
+
+        final Format value = Format.forValue(format);
+        switch (value) {
+            case RAW:
+                final Project project = optional.get();
+                LOGGER.info("found project {} in cache", project);
+                return ResponseEntity.ok(project);
+            case COUNT:
+                final Map<String, Object> map = new HashMap<>();
+                map.put(PROJECT, 1);
+                return ResponseEntity.ok(new Results(map));
+            default:
+                break;
+        }
+        LOGGER.error("invalid format type :{}", format);
+        return getRequestErrorResponseEntity(request);
+    }
+
+    @PutMapping(value = "/{project-name}" + RELATIONSHIP_LIST_RELATIONSHIP_URL,
+            consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+            produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public ResponseEntity<?> putProjectRelationShip(@RequestBody final Relationship relationship,
+            @PathVariable("project-name") final String projectName, final HttpServletRequest request) {
+
+        LOGGER.info("adding relationship for project-name: {} ...", projectName);
+
+        if (relationship.getRelatedLink() != null) {
+            final String targetBaseUrl = HttpServiceUtils.getBaseUrl(request).toString();
+            final HttpHeaders incomingHeader = getHeaders(request);
+
+            final boolean result = cacheServiceProvider.addRelationShip(incomingHeader, targetBaseUrl,
+                    request.getRequestURI(), projectName, relationship);
+            if (result) {
+                LOGGER.info("added created bi directional relationship with {}", relationship.getRelatedLink());
+                return ResponseEntity.accepted().build();
+            }
+        }
+
+        LOGGER.error("Unable to add relationship for related link: {}", relationship.getRelatedLink());
+        return getRequestErrorResponseEntity(request);
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/exception/InvalidRestRequestException.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/exception/InvalidRestRequestException.java
new file mode 100755 (executable)
index 0000000..4a7c289
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.aaisimulator.exception;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class InvalidRestRequestException extends RuntimeException {
+    private static final long serialVersionUID = -1158414939006977465L;
+
+    public InvalidRestRequestException(final String message) {
+        super(message);
+    }
+
+    public InvalidRestRequestException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/exception/RestProcessingException.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/exception/RestProcessingException.java
new file mode 100755 (executable)
index 0000000..0a93e2f
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.exception;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class RestProcessingException extends RuntimeException {
+
+    private static final long serialVersionUID = 16862313537198441L;
+
+    public RestProcessingException(final String message) {
+        super(message);
+    }
+
+    public RestProcessingException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/CloudRegionKey.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/CloudRegionKey.java
new file mode 100755 (executable)
index 0000000..3c45c19
--- /dev/null
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.models;
+
+import java.io.Serializable;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class CloudRegionKey implements Serializable {
+
+    private static final long serialVersionUID = 6175094050996035737L;
+
+    private final String cloudOwner;
+
+    private final String cloudRegionId;
+
+    public CloudRegionKey(final String cloudOwner, final String cloudRegionId) {
+        this.cloudOwner = cloudOwner;
+        this.cloudRegionId = cloudRegionId;
+    }
+
+    /**
+     * @return the cloudOwner
+     */
+    public String getCloudOwner() {
+        return cloudOwner;
+    }
+
+    /**
+     * @return the cloudRegionId
+     */
+    public String getCloudRegionId() {
+        return cloudRegionId;
+    }
+
+    public boolean isValid() {
+        return cloudOwner != null && !cloudOwner.isEmpty() && cloudRegionId != null && !cloudRegionId.isEmpty();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (ObjectUtils.nullSafeHashCode(cloudOwner));
+        result = prime * result + (ObjectUtils.nullSafeHashCode(cloudRegionId));
+
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof CloudRegionKey) {
+            final CloudRegionKey other = (CloudRegionKey) obj;
+            return ObjectUtils.nullSafeEquals(cloudOwner, other.cloudOwner)
+                    && ObjectUtils.nullSafeEquals(cloudRegionId, other.cloudRegionId);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "CloudRegionKey [cloudOwner=" + cloudOwner + ", cloudRegionId=" + cloudRegionId + "]";
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/Format.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/Format.java
new file mode 100755 (executable)
index 0000000..1c851fc
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.models;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public enum Format {
+
+    COUNT("count"), RAW("raw"), PATHED("pathed");
+
+    private final String value;
+
+    private Format(final String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public static Format forValue(final String value) {
+        for (final Format format : Format.values()) {
+            if (format.getValue().equals(value)) {
+                return format;
+            }
+        }
+        return RAW;
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/NodeServiceInstance.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/NodeServiceInstance.java
new file mode 100755 (executable)
index 0000000..4a64591
--- /dev/null
@@ -0,0 +1,139 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.models;
+
+import java.io.Serializable;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class NodeServiceInstance implements Serializable {
+
+    private static final long serialVersionUID = -3314166327618070948L;
+
+    private String globalCustomerId;
+    private String serviceType;
+    private String serviceInstanceId;
+    private String resourceType;
+    private String resourceLink;
+
+    public NodeServiceInstance() {}
+
+
+    public NodeServiceInstance(final String globalCustomerId, final String serviceType, final String serviceInstanceId,
+            final String resourceType, final String resourceLink) {
+        this.globalCustomerId = globalCustomerId;
+        this.serviceType = serviceType;
+        this.serviceInstanceId = serviceInstanceId;
+        this.resourceType = resourceType;
+        this.resourceLink = resourceLink;
+    }
+
+
+    /**
+     * @return the globalCustomerId
+     */
+    public String getGlobalCustomerId() {
+        return globalCustomerId;
+    }
+
+
+    /**
+     * @param globalCustomerId the globalCustomerId to set
+     */
+    public void setGlobalCustomerId(final String globalCustomerId) {
+        this.globalCustomerId = globalCustomerId;
+    }
+
+
+    /**
+     * @return the serviceType
+     */
+    public String getServiceType() {
+        return serviceType;
+    }
+
+
+    /**
+     * @param serviceType the serviceType to set
+     */
+    public void setServiceType(final String serviceType) {
+        this.serviceType = serviceType;
+    }
+
+
+    /**
+     * @return the serviceInstanceId
+     */
+    public String getServiceInstanceId() {
+        return serviceInstanceId;
+    }
+
+
+    /**
+     * @param serviceInstanceId the serviceInstanceId to set
+     */
+    public void setServiceInstanceId(final String serviceInstanceId) {
+        this.serviceInstanceId = serviceInstanceId;
+    }
+
+
+    /**
+     * @return the resourceType
+     */
+    public String getResourceType() {
+        return resourceType;
+    }
+
+
+    /**
+     * @param resourceType the resourceType to set
+     */
+    public void setResourceType(final String resourceType) {
+        this.resourceType = resourceType;
+    }
+
+
+    /**
+     * @return the resourceLink
+     */
+    public String getResourceLink() {
+        return resourceLink;
+    }
+
+
+    /**
+     * @param resourceLink the resourceLink to set
+     */
+    public void setResourceLink(final String resourceLink) {
+        this.resourceLink = resourceLink;
+    }
+
+
+    @Override
+    public String toString() {
+        return "NodeServiceInstance [globalCustomerId=" + globalCustomerId + ", serviceType=" + serviceType
+                + ", serviceInstanceId=" + serviceInstanceId + ", resourceType=" + resourceType + ", resourceLink="
+                + resourceLink + "]";
+    }
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/Results.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/Results.java
new file mode 100755 (executable)
index 0000000..8dc2024
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.models;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class Results implements Serializable {
+
+    private static final long serialVersionUID = 3967660859271162759L;
+
+    @JsonProperty("results")
+    private List<Map<String, Object>> values = new ArrayList<>();
+
+    public Results() {}
+
+    public Results(final Map<String, Object> value) {
+        this.values.add(value);
+    }
+
+    /**
+     * @return the values
+     */
+    public List<Map<String, Object>> getValues() {
+        return values;
+    }
+
+    /**
+     * @param values the values to set
+     */
+    public void setValues(final List<Map<String, Object>> values) {
+        this.values = values;
+    }
+
+
+    @JsonIgnore
+    @Override
+    public String toString() {
+        return "Result [values=" + values + "]";
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/Clearable.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/Clearable.java
new file mode 100755 (executable)
index 0000000..dd4ace4
--- /dev/null
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface Clearable {
+    void clearAll();
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CloudRegionCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CloudRegionCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..6facac8
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.onap.aai.domain.yang.CloudRegion;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrSystemInfoList;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.Tenant;
+import org.onap.aai.domain.yang.Vserver;
+import org.onap.so.aaisimulator.models.CloudRegionKey;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface CloudRegionCacheServiceProvider extends Clearable {
+
+    void putCloudRegion(final CloudRegionKey cloudRegionKey, final CloudRegion cloudRegion);
+
+    Optional<CloudRegion> getCloudRegion(final CloudRegionKey cloudRegionKey);
+
+    Optional<Relationship> addRelationShip(final CloudRegionKey key, final Relationship relationship,
+            final String requestUri);
+
+    boolean putTenant(final CloudRegionKey key, final String tenantId, Tenant tenant);
+
+    Optional<Tenant> getTenant(final CloudRegionKey key, final String tenantId);
+
+    boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl, final String requestURI,
+            final CloudRegionKey key, final String tenantId, final Relationship relationship);
+
+    Optional<EsrSystemInfoList> getEsrSystemInfoList(final CloudRegionKey key);
+
+    boolean putEsrSystemInfo(final CloudRegionKey key, final String esrSystemInfoId, final EsrSystemInfo esrSystemInfo);
+
+    boolean putVserver(final CloudRegionKey key, final String tenantId, final String vServerId, Vserver vServer);
+
+    Optional<Vserver> getVserver(final CloudRegionKey key, final String tenantId, final String vServerId);
+
+    boolean deleteVserver(final CloudRegionKey key, final String tenantId, final String vServerId,
+            final String resourceVersion);
+
+    Optional<Relationship> addvServerRelationShip(final CloudRegionKey key, final String tenantId,
+            final String vServerId, final Relationship relationship, final String requestUri);
+
+    boolean addVServerRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl, final String requestURI, final CloudRegionKey key,
+            final String tenantId, final String vServerId, final Relationship relationship);
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CloudRegionCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CloudRegionCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..f1f782a
--- /dev/null
@@ -0,0 +1,471 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.CLOUD_REGION_CACHE;
+import static org.onap.so.aaisimulator.utils.Constants.BELONGS_TO;
+import static org.onap.so.aaisimulator.utils.Constants.CLOUD_REGION;
+import static org.onap.so.aaisimulator.utils.Constants.CLOUD_REGION_CLOUD_OWNER;
+import static org.onap.so.aaisimulator.utils.Constants.CLOUD_REGION_CLOUD_REGION_ID;
+import static org.onap.so.aaisimulator.utils.Constants.CLOUD_REGION_OWNER_DEFINED_TYPE;
+import static org.onap.so.aaisimulator.utils.Constants.HOSTED_ON;
+import static org.onap.so.aaisimulator.utils.Constants.LOCATED_IN;
+import static org.onap.so.aaisimulator.utils.Constants.TENANT;
+import static org.onap.so.aaisimulator.utils.Constants.TENANT_TENANT_ID;
+import static org.onap.so.aaisimulator.utils.Constants.TENANT_TENANT_NAME;
+import static org.onap.so.aaisimulator.utils.Constants.VSERVER;
+import static org.onap.so.aaisimulator.utils.Constants.VSERVER_VSERVER_ID;
+import static org.onap.so.aaisimulator.utils.Constants.VSERVER_VSERVER_NAME;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getBiDirectionalRelationShipListRelatedLink;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getRelationShipListRelatedLink;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getTargetUrl;
+import java.util.List;
+import java.util.Optional;
+import org.onap.aai.domain.yang.CloudRegion;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrSystemInfoList;
+import org.onap.aai.domain.yang.RelatedToProperty;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.aai.domain.yang.Tenant;
+import org.onap.aai.domain.yang.Tenants;
+import org.onap.aai.domain.yang.Vserver;
+import org.onap.aai.domain.yang.Vservers;
+import org.onap.so.aaisimulator.models.CloudRegionKey;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class CloudRegionCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements CloudRegionCacheServiceProvider {
+
+
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CloudRegionCacheServiceProviderImpl.class);
+
+    private final HttpRestServiceProvider httpRestServiceProvider;
+
+    @Autowired
+    public CloudRegionCacheServiceProviderImpl(final CacheManager cacheManager,
+            final HttpRestServiceProvider httpRestServiceProvider) {
+        super(cacheManager);
+        this.httpRestServiceProvider = httpRestServiceProvider;
+    }
+
+    @Override
+    public void putCloudRegion(final CloudRegionKey cloudRegionKey, final CloudRegion cloudRegion) {
+        LOGGER.info("Adding CloudRegion to cache with key: {} ...", cloudRegionKey);
+        final Cache cache = getCache(CLOUD_REGION_CACHE.getName());
+        cache.put(cloudRegionKey, cloudRegion);
+
+    }
+
+    @Override
+    public Optional<CloudRegion> getCloudRegion(final CloudRegionKey cloudRegionKey) {
+        LOGGER.info("getting CloudRegion from cache using key: {}", cloudRegionKey);
+        final Cache cache = getCache(CLOUD_REGION_CACHE.getName());
+        final CloudRegion value = cache.get(cloudRegionKey, CloudRegion.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        LOGGER.error("Unable to find CloudRegion in cache using key:{} ", cloudRegionKey);
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<Relationship> addRelationShip(final CloudRegionKey key, final Relationship relationship,
+            final String requestUri) {
+        final Optional<CloudRegion> optional = getCloudRegion(key);
+        if (optional.isPresent()) {
+            final CloudRegion cloudRegion = optional.get();
+            RelationshipList relationshipList = cloudRegion.getRelationshipList();
+            if (relationshipList == null) {
+                relationshipList = new RelationshipList();
+                cloudRegion.setRelationshipList(relationshipList);
+            }
+            relationshipList.getRelationship().add(relationship);
+
+            LOGGER.info("Successfully added relation to CloudRegion with key: {}", key);
+
+
+            final Relationship resultantRelationship = new Relationship();
+            resultantRelationship.setRelatedTo(CLOUD_REGION);
+            resultantRelationship.setRelationshipLabel(LOCATED_IN);
+            resultantRelationship.setRelatedLink(getBiDirectionalRelationShipListRelatedLink(requestUri));
+
+            final List<RelationshipData> relationshipDataList = resultantRelationship.getRelationshipData();
+            relationshipDataList.add(getRelationshipData(CLOUD_REGION_CLOUD_OWNER, cloudRegion.getCloudOwner()));
+            relationshipDataList.add(getRelationshipData(CLOUD_REGION_CLOUD_REGION_ID, cloudRegion.getCloudRegionId()));
+
+            final List<RelatedToProperty> relatedToPropertyList = resultantRelationship.getRelatedToProperty();
+
+            final RelatedToProperty relatedToProperty = new RelatedToProperty();
+            relatedToProperty.setPropertyKey(CLOUD_REGION_OWNER_DEFINED_TYPE);
+            relatedToProperty.setPropertyValue(cloudRegion.getOwnerDefinedType());
+            relatedToPropertyList.add(relatedToProperty);
+
+            return Optional.of(resultantRelationship);
+
+        }
+        LOGGER.error("Unable to find CloudRegion using key: {} ...", key);
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean putTenant(final CloudRegionKey key, final String tenantId, final Tenant tenant) {
+        final Optional<CloudRegion> optional = getCloudRegion(key);
+        if (optional.isPresent()) {
+            final CloudRegion cloudRegion = optional.get();
+            Tenants tenants = cloudRegion.getTenants();
+            if (tenants == null) {
+                tenants = new Tenants();
+                cloudRegion.setTenants(tenants);
+            }
+
+            final Optional<Tenant> existingTenantOptional = tenants.getTenant().stream()
+                    .filter(existing -> existing.getTenantId() != null && existing.getTenantId().equals(tenantId))
+                    .findFirst();
+
+            if (!existingTenantOptional.isPresent()) {
+                return tenants.getTenant().add(tenant);
+            }
+
+            LOGGER.warn("Tenant already exists ...");
+            return false;
+        }
+        LOGGER.error("Unable to add Tenant using key: {} ...", key);
+        return false;
+    }
+
+    @Override
+    public Optional<Tenant> getTenant(final CloudRegionKey key, final String tenantId) {
+        final Optional<CloudRegion> optional = getCloudRegion(key);
+        if (optional.isPresent()) {
+            final CloudRegion cloudRegion = optional.get();
+            final Tenants tenants = cloudRegion.getTenants();
+            if (tenants != null) {
+                return tenants.getTenant().stream().filter(existing -> existing.getTenantId().equals(tenantId))
+                        .findFirst();
+            }
+        }
+
+        LOGGER.error("Unable to find Tenant using key: {} and tenantId: {} ...", key, tenantId);
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl,
+            final String requestUriString, final CloudRegionKey key, final String tenantId,
+            final Relationship relationship) {
+        try {
+            final Optional<Tenant> optional = getTenant(key, tenantId);
+            if (optional.isPresent()) {
+                final Tenant tenant = optional.get();
+                final String targetUrl = getTargetUrl(targetBaseUrl, relationship.getRelatedLink());
+
+                final Relationship outGoingRelationShip = getRelationship(requestUriString, key, tenant);
+                final Optional<Relationship> optionalRelationship = httpRestServiceProvider.put(incomingHeader,
+                        outGoingRelationShip, targetUrl, Relationship.class);
+
+                if (optionalRelationship.isPresent()) {
+                    final Relationship resultantRelationship = optionalRelationship.get();
+                    RelationshipList relationshipList = tenant.getRelationshipList();
+                    if (relationshipList == null) {
+                        relationshipList = new RelationshipList();
+                        tenant.setRelationshipList(relationshipList);
+                    }
+
+                    if (relationshipList.getRelationship().add(resultantRelationship)) {
+                        LOGGER.info("added relationship {} in cache successfully", resultantRelationship);
+                        return true;
+                    }
+                }
+
+
+            }
+        } catch (final Exception exception) {
+            LOGGER.error("Unable to add two-way relationship for CloudRegion: {} and tenant: {}", key, tenantId,
+                    exception);
+        }
+        LOGGER.error("Unable to add relationship in cache for CloudRegion: {} and tenant: {}", key, tenantId);
+        return false;
+    }
+
+    @Override
+    public Optional<EsrSystemInfoList> getEsrSystemInfoList(final CloudRegionKey key) {
+        final Optional<CloudRegion> optional = getCloudRegion(key);
+        if (optional.isPresent()) {
+            final CloudRegion cloudRegion = optional.get();
+            final EsrSystemInfoList esrSystemInfoList = cloudRegion.getEsrSystemInfoList();
+            if (esrSystemInfoList != null) {
+                return Optional.of(esrSystemInfoList);
+            }
+        }
+        LOGGER.error("Unable to find EsrSystemInfoList in cache for CloudRegion: {} ", key);
+
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean putEsrSystemInfo(final CloudRegionKey key, final String esrSystemInfoId,
+            final EsrSystemInfo esrSystemInfo) {
+        final Optional<CloudRegion> optional = getCloudRegion(key);
+        if (optional.isPresent()) {
+            final CloudRegion cloudRegion = optional.get();
+            final List<EsrSystemInfo> esrSystemInfoList = getEsrSystemInfoList(cloudRegion);
+
+            final Optional<EsrSystemInfo> existingEsrSystemInfo =
+                    esrSystemInfoList.stream().filter(existing -> existing.getEsrSystemInfoId() != null
+                            && existing.getEsrSystemInfoId().equals(esrSystemInfoId)).findFirst();
+            if (existingEsrSystemInfo.isPresent()) {
+                LOGGER.error("EsrSystemInfo already exists {}", existingEsrSystemInfo.get());
+                return false;
+            }
+
+            return esrSystemInfoList.add(esrSystemInfo);
+
+        }
+        return false;
+    }
+
+    @Override
+    public boolean putVserver(final CloudRegionKey key, final String tenantId, final String vServerId,
+            final Vserver vServer) {
+        final Optional<Tenant> optional = getTenant(key, tenantId);
+        if (optional.isPresent()) {
+            final Tenant tenant = optional.get();
+            Vservers vServers = tenant.getVservers();
+            if (vServers == null) {
+                vServers = new Vservers();
+                tenant.setVservers(vServers);
+            }
+            final List<Vserver> vServerList = vServers.getVserver();
+
+            final Optional<Vserver> existingVserver = vServerList.stream()
+                    .filter(existing -> existing.getVserverId() != null && existing.getVserverId().equals(vServerId))
+                    .findFirst();
+
+            if (existingVserver.isPresent()) {
+                LOGGER.error("Vserver already exists {}", existingVserver.get());
+                return false;
+            }
+            return vServerList.add(vServer);
+
+        }
+        return false;
+    }
+
+    @Override
+    public Optional<Vserver> getVserver(final CloudRegionKey key, final String tenantId, final String vServerId) {
+        final Optional<Tenant> optional = getTenant(key, tenantId);
+        if (optional.isPresent()) {
+            final Tenant tenant = optional.get();
+            final Vservers vServers = tenant.getVservers();
+            if (vServers != null) {
+                return vServers.getVserver().stream()
+                        .filter(vServer -> vServer.getVserverId() != null && vServer.getVserverId().equals(vServerId))
+                        .findFirst();
+            }
+        }
+        LOGGER.error("Unable to find vServer in cache ... ");
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean deleteVserver(final CloudRegionKey key, final String tenantId, final String vServerId,
+            final String resourceVersion) {
+        final Optional<Vserver> optional = getVserver(key, tenantId, vServerId);
+        if (optional.isPresent()) {
+            final Optional<Tenant> tenantOptional = getTenant(key, tenantId);
+            if (tenantOptional.isPresent()) {
+                final Tenant tenant = tenantOptional.get();
+                final Vservers vServers = tenant.getVservers();
+                if (vServers != null) {
+                    return vServers.getVserver().removeIf(vServer -> {
+                        if (vServer.getVserverId() != null && vServer.getVserverId().equals(vServerId)
+                                && vServer.getResourceVersion() != null
+                                && vServer.getResourceVersion().equals(resourceVersion)) {
+                            LOGGER.info("Will remove Vserver from cache with vServerId: {} and resource-version: {} ",
+                                    vServerId, vServer.getResourceVersion());
+                            return true;
+                        }
+                        return false;
+                    });
+                }
+
+            }
+
+        }
+        LOGGER.error(
+                "Unable to find Vserver for using key: {}, tenant-id: {}, vserver-id: {} and resource-version: {} ...",
+                key, tenantId, vServerId, resourceVersion);
+
+        return false;
+    }
+
+    @Override
+    public Optional<Relationship> addvServerRelationShip(final CloudRegionKey key, final String tenantId,
+            final String vServerId, final Relationship relationship, final String requestUri) {
+        final Optional<Vserver> optional = getVserver(key, tenantId, vServerId);
+        if (optional.isPresent()) {
+            final Vserver vServer = optional.get();
+            RelationshipList relationshipList = vServer.getRelationshipList();
+            if (relationshipList == null) {
+                relationshipList = new RelationshipList();
+                vServer.setRelationshipList(relationshipList);
+            }
+            relationshipList.getRelationship().add(relationship);
+            LOGGER.info("Successfully added relation to Vserver with key: {}, tenantId: {} and vServerId: {}", key,
+                    tenantId, vServerId);
+            final String relatedLink = getBiDirectionalRelationShipListRelatedLink(requestUri);
+
+            final Relationship resultantRelationship = getVserverRelationship(key, tenantId, vServer, relatedLink);
+
+            return Optional.of(resultantRelationship);
+        }
+
+        LOGGER.error("Unable to find Vserver using key: {}, tenantId: {} and vServerId: {}...", key, tenantId,
+                vServerId);
+        return Optional.empty();
+    }
+
+    private Relationship getVserverRelationship(final CloudRegionKey key, final String tenantId, final Vserver vServer,
+            final String relatedLink) {
+        final Relationship resultantRelationship = new Relationship();
+        resultantRelationship.setRelatedTo(VSERVER);
+        resultantRelationship.setRelationshipLabel(HOSTED_ON);
+        resultantRelationship.setRelatedLink(relatedLink);
+
+        final List<RelationshipData> relationshipDataList = resultantRelationship.getRelationshipData();
+        relationshipDataList.add(getRelationshipData(CLOUD_REGION_CLOUD_OWNER, key.getCloudOwner()));
+        relationshipDataList.add(getRelationshipData(CLOUD_REGION_CLOUD_REGION_ID, key.getCloudRegionId()));
+        relationshipDataList.add(getRelationshipData(TENANT_TENANT_ID, tenantId));
+        relationshipDataList.add(getRelationshipData(VSERVER_VSERVER_ID, vServer.getVserverId()));
+
+        final List<RelatedToProperty> relatedToPropertyList = resultantRelationship.getRelatedToProperty();
+
+        final RelatedToProperty relatedToProperty = new RelatedToProperty();
+        relatedToProperty.setPropertyKey(VSERVER_VSERVER_NAME);
+        relatedToProperty.setPropertyValue(vServer.getVserverName());
+        relatedToPropertyList.add(relatedToProperty);
+        return resultantRelationship;
+    }
+
+    @Override
+    public boolean addVServerRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl,
+            final String requestUriString, final CloudRegionKey key, final String tenantId, final String vServerId,
+            final Relationship relationship) {
+        try {
+            final Optional<Vserver> optional = getVserver(key, tenantId, vServerId);
+            if (optional.isPresent()) {
+                final Vserver vServer = optional.get();
+                final String targetUrl = getTargetUrl(targetBaseUrl, relationship.getRelatedLink());
+                final Relationship outGoingRelationShip = getVserverRelationship(key, tenantId, vServer,
+                        getRelationShipListRelatedLink(requestUriString));
+                final Optional<Relationship> optionalRelationship = httpRestServiceProvider.put(incomingHeader,
+                        outGoingRelationShip, targetUrl, Relationship.class);
+                if (optionalRelationship.isPresent()) {
+                    final Relationship resultantRelationship = optionalRelationship.get();
+
+                    RelationshipList relationshipList = vServer.getRelationshipList();
+                    if (relationshipList == null) {
+                        relationshipList = new RelationshipList();
+                        vServer.setRelationshipList(relationshipList);
+                    }
+
+                    final Optional<Relationship> relationShipExists = relationshipList.getRelationship().stream()
+                            .filter(relation -> relation.getRelatedTo().equals(resultantRelationship.getRelatedTo())
+                                    && relation.getRelatedLink().equals(resultantRelationship.getRelatedLink()))
+                            .findAny();
+
+                    if (relationShipExists.isPresent()) {
+                        LOGGER.info("relationship {} already exists in cache ", resultantRelationship);
+                        return true;
+                    }
+
+                    LOGGER.info("added relationship {} in cache successfully", resultantRelationship);
+                    return relationshipList.getRelationship().add(resultantRelationship);
+                }
+
+            }
+        } catch (final Exception exception) {
+            LOGGER.error("Unable to add two-way relationship for key: {}, tenantId: {} and vServerId: {}", key,
+                    tenantId, vServerId, exception);
+        }
+        LOGGER.error("Unable to add Vserver relationship for key: {}, tenantId: {} and vServerId: {}...", key, tenantId,
+                vServerId);
+        return false;
+    }
+
+    private List<EsrSystemInfo> getEsrSystemInfoList(final CloudRegion cloudRegion) {
+        EsrSystemInfoList esrSystemInfoList = cloudRegion.getEsrSystemInfoList();
+        if (esrSystemInfoList == null) {
+            esrSystemInfoList = new EsrSystemInfoList();
+            cloudRegion.setEsrSystemInfoList(esrSystemInfoList);
+        }
+        return esrSystemInfoList.getEsrSystemInfo();
+    }
+
+    private Relationship getRelationship(final String requestUriString, final CloudRegionKey cloudRegionKey,
+            final Tenant tenant) {
+        final Relationship relationShip = new Relationship();
+        relationShip.setRelatedTo(TENANT);
+        relationShip.setRelationshipLabel(BELONGS_TO);
+        relationShip.setRelatedLink(getRelationShipListRelatedLink(requestUriString));
+
+
+        final List<RelationshipData> relationshipDataList = relationShip.getRelationshipData();
+        relationshipDataList.add(getRelationshipData(CLOUD_REGION_CLOUD_OWNER, cloudRegionKey.getCloudOwner()));
+        relationshipDataList.add(getRelationshipData(CLOUD_REGION_CLOUD_REGION_ID, cloudRegionKey.getCloudRegionId()));
+        relationshipDataList.add(getRelationshipData(TENANT_TENANT_ID, tenant.getTenantId()));
+
+
+        final RelatedToProperty relatedToProperty = new RelatedToProperty();
+        relatedToProperty.setPropertyKey(TENANT_TENANT_NAME);
+        relatedToProperty.setPropertyValue(tenant.getTenantName());
+        relationShip.getRelatedToProperty().add(relatedToProperty);
+        return relationShip;
+    }
+
+    private RelationshipData getRelationshipData(final String key, final String value) {
+        final RelationshipData relationshipData = new RelationshipData();
+        relationshipData.setRelationshipKey(key);
+        relationshipData.setRelationshipValue(value);
+        return relationshipData;
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(CLOUD_REGION_CACHE.getName());
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..7000fb3
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.onap.aai.domain.yang.Customer;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.aai.domain.yang.ServiceInstances;
+import org.onap.aai.domain.yang.ServiceSubscription;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public interface CustomerCacheServiceProvider extends Clearable {
+
+    Optional<Customer> getCustomer(final String globalCustomerId);
+
+    void putCustomer(final String globalCustomerId, final Customer customer);
+
+    Optional<ServiceSubscription> getServiceSubscription(final String globalCustomerId, final String serviceType);
+
+    boolean putServiceSubscription(final String globalCustomerId, final String serviceType,
+            final ServiceSubscription serviceSubscription);
+
+    Optional<ServiceInstances> getServiceInstances(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceName);
+
+    Optional<ServiceInstance> getServiceInstance(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId);
+
+    boolean putServiceInstance(final String globalCustomerId, final String serviceType, final String serviceInstanceId,
+            final ServiceInstance serviceInstance);
+
+    boolean patchServiceInstance(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final ServiceInstance serviceInstance);
+
+    Optional<Relationship> getRelationship(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final String vnfName);
+
+    Optional<Relationship> addRelationShip(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final Relationship relationship, final String requestUri);
+
+    boolean deleteSericeInstance(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final String resourceVersion);
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..7193ade
--- /dev/null
@@ -0,0 +1,365 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.CUSTOMER_CACHE;
+import static org.onap.so.aaisimulator.utils.Constants.CUSTOMER_GLOBAL_CUSTOMER_ID;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF_VNF_NAME;
+import static org.onap.so.aaisimulator.utils.Constants.SERVICE_INSTANCE_SERVICE_INSTANCE_ID;
+import static org.onap.so.aaisimulator.utils.Constants.SERVICE_INSTANCE_SERVICE_INSTANCE_NAME;
+import static org.onap.so.aaisimulator.utils.Constants.SERVICE_SUBSCRIPTION_SERVICE_TYPE;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getBiDirectionalRelationShipListRelatedLink;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.onap.aai.domain.yang.Customer;
+import org.onap.aai.domain.yang.RelatedToProperty;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.aai.domain.yang.ServiceInstances;
+import org.onap.aai.domain.yang.ServiceSubscription;
+import org.onap.aai.domain.yang.ServiceSubscriptions;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Service
+public class CustomerCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements CustomerCacheServiceProvider {
+    private static final Logger LOGGER = LoggerFactory.getLogger(CustomerCacheServiceProviderImpl.class);
+
+    @Autowired
+    public CustomerCacheServiceProviderImpl(final CacheManager cacheManager) {
+        super(cacheManager);
+    }
+
+    @Override
+    public Optional<Customer> getCustomer(final String globalCustomerId) {
+        LOGGER.info("getting customer from cache using key: {}", globalCustomerId);
+        final Cache cache = getCache(CUSTOMER_CACHE.getName());
+        final Customer value = cache.get(globalCustomerId, Customer.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public void putCustomer(final String globalCustomerId, final Customer customer) {
+        LOGGER.info("Adding customer: {} with key: {} in cache ...", customer, globalCustomerId);
+        final Cache cache = getCache(CUSTOMER_CACHE.getName());
+
+        cache.put(globalCustomerId, customer);
+    }
+
+    @Override
+    public Optional<ServiceSubscription> getServiceSubscription(final String globalCustomerId,
+            final String serviceType) {
+        LOGGER.info("getting service subscription from cache for globalCustomerId: {} and serviceType: {}",
+                globalCustomerId, serviceType);
+
+        final Cache cache = getCache(CUSTOMER_CACHE.getName());
+
+        final Customer value = cache.get(globalCustomerId, Customer.class);
+
+        if (value != null) {
+            return Optional.ofNullable(value.getServiceSubscriptions().getServiceSubscription().stream()
+                    .filter(s -> serviceType.equals(s.getServiceType())).findFirst().orElse(null));
+        }
+        return Optional.empty();
+
+    }
+
+    @Override
+    public Optional<ServiceInstances> getServiceInstances(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceName) {
+
+        final Cache cache = getCache(CUSTOMER_CACHE.getName());
+        final Customer value = cache.get(globalCustomerId, Customer.class);
+
+        if (value != null) {
+            final Optional<ServiceSubscription> serviceSubscription = value.getServiceSubscriptions()
+                    .getServiceSubscription().stream().filter(s -> serviceType.equals(s.getServiceType())).findFirst();
+
+            if (serviceSubscription.isPresent()) {
+                LOGGER.info("Found service subscription ...");
+                final ServiceInstances serviceInstances = serviceSubscription.get().getServiceInstances();
+                if (serviceInstances != null) {
+                    final List<ServiceInstance> serviceInstancesList =
+                            serviceInstances.getServiceInstance().stream()
+                                    .filter(serviceInstance -> serviceInstanceName
+                                            .equals(serviceInstance.getServiceInstanceName()))
+                                    .collect(Collectors.toList());
+                    if (serviceInstancesList != null && !serviceInstancesList.isEmpty()) {
+                        LOGGER.info("Found {} service instances ", serviceInstancesList.size());
+                        final ServiceInstances result = new ServiceInstances();
+                        result.getServiceInstance().addAll(serviceInstancesList);
+                        return Optional.of(result);
+
+                    }
+                }
+            }
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<ServiceInstance> getServiceInstance(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId) {
+        final Cache cache = getCache(CUSTOMER_CACHE.getName());
+        final Customer value = cache.get(globalCustomerId, Customer.class);
+
+        if (value != null) {
+            final Optional<ServiceSubscription> serviceSubscription = value.getServiceSubscriptions()
+                    .getServiceSubscription().stream().filter(s -> serviceType.equals(s.getServiceType())).findFirst();
+
+            if (serviceSubscription.isPresent()) {
+                LOGGER.info("Found service subscription ...");
+                final ServiceInstances serviceInstances = serviceSubscription.get().getServiceInstances();
+                if (serviceInstances != null) {
+                    return Optional.ofNullable(serviceInstances.getServiceInstance().stream()
+                            .filter(serviceInstance -> serviceInstanceId.equals(serviceInstance.getServiceInstanceId()))
+                            .findFirst().orElse(null));
+                }
+
+            }
+        }
+        LOGGER.error(
+                "Unable to find ServiceInstance using globalCustomerId: {}, serviceType: {} and serviceInstanceId: {} ...",
+                globalCustomerId, serviceType, serviceInstanceId);
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean putServiceInstance(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final ServiceInstance serviceInstance) {
+        LOGGER.info("Adding serviceInstance: {} in cache ...", serviceInstance, globalCustomerId);
+
+        final Cache cache = getCache(CUSTOMER_CACHE.getName());
+        final Customer value = cache.get(globalCustomerId, Customer.class);
+
+        if (value != null) {
+            final Optional<ServiceSubscription> serviceSubscription = value.getServiceSubscriptions()
+                    .getServiceSubscription().stream().filter(s -> serviceType.equals(s.getServiceType())).findFirst();
+
+            if (serviceSubscription.isPresent()) {
+                final ServiceInstances serviceInstances = getServiceInstances(serviceSubscription);
+
+
+                if (!serviceInstances.getServiceInstance().stream()
+                        .filter(existing -> serviceInstanceId.equals(existing.getServiceInstanceId())).findFirst()
+                        .isPresent()) {
+                    return serviceInstances.getServiceInstance().add(serviceInstance);
+                }
+                LOGGER.error("Service {} already exists ....", serviceInstanceId);
+                return false;
+            }
+            LOGGER.error("Couldn't find  service subscription with serviceType: {} in cache ", serviceType);
+            return false;
+        }
+        LOGGER.error("Couldn't find  Customer with key: {} in cache ", globalCustomerId);
+        return false;
+    }
+
+    @Override
+    public boolean putServiceSubscription(final String globalCustomerId, final String serviceType,
+            final ServiceSubscription serviceSubscription) {
+
+        final Optional<Customer> customerOptional = getCustomer(globalCustomerId);
+
+        if (customerOptional.isPresent()) {
+            final Customer customer = customerOptional.get();
+            if (customer.getServiceSubscriptions() == null) {
+                final ServiceSubscriptions serviceSubscriptions = new ServiceSubscriptions();
+                customer.setServiceSubscriptions(serviceSubscriptions);
+                return serviceSubscriptions.getServiceSubscription().add(serviceSubscription);
+            }
+
+            final Optional<ServiceSubscription> serviceSubscriptionOptional = customer.getServiceSubscriptions()
+                    .getServiceSubscription().stream().filter(s -> serviceType.equals(s.getServiceType())).findFirst();
+
+            if (!serviceSubscriptionOptional.isPresent()) {
+                return customer.getServiceSubscriptions().getServiceSubscription().add(serviceSubscription);
+            }
+            LOGGER.error("ServiceSubscription already exists {}", serviceSubscriptionOptional.get().getServiceType());
+            return false;
+        }
+        LOGGER.error("Unable to add ServiceSubscription to cache becuase customer does not exits ...");
+        return false;
+    }
+
+    @Override
+    public boolean patchServiceInstance(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final ServiceInstance serviceInstance) {
+        final Optional<ServiceInstance> instance = getServiceInstance(globalCustomerId, serviceType, serviceInstanceId);
+        if (instance.isPresent()) {
+            final ServiceInstance cachedServiceInstance = instance.get();
+            LOGGER.info("Changing OrchestrationStatus from {} to {} ", cachedServiceInstance.getOrchestrationStatus(),
+                    serviceInstance.getOrchestrationStatus());
+            cachedServiceInstance.setOrchestrationStatus(serviceInstance.getOrchestrationStatus());
+            return true;
+        }
+        LOGGER.error("Unable to find ServiceInstance ...");
+        return false;
+    }
+
+    @Override
+    public boolean deleteSericeInstance(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final String resourceVersion) {
+        final Cache cache = getCache(CUSTOMER_CACHE.getName());
+        final Customer value = cache.get(globalCustomerId, Customer.class);
+
+        if (value != null) {
+            final Optional<ServiceSubscription> serviceSubscription = value.getServiceSubscriptions()
+                    .getServiceSubscription().stream().filter(s -> serviceType.equals(s.getServiceType())).findFirst();
+
+            if (serviceSubscription.isPresent()) {
+                LOGGER.info("Found service subscription ...");
+                final ServiceInstances serviceInstances = serviceSubscription.get().getServiceInstances();
+                if (serviceInstances != null) {
+
+                    serviceInstances.getServiceInstance().removeIf(serviceInstance -> {
+                        final String existingServiceInstanceId = serviceInstance.getServiceInstanceId();
+                        final String existingResourceVersion = serviceInstance.getResourceVersion();
+                        if (existingServiceInstanceId != null && existingServiceInstanceId.equals(serviceInstanceId)
+                                && existingResourceVersion != null && existingResourceVersion.equals(resourceVersion)) {
+                            LOGGER.info("Removing ServiceInstance with serviceInstanceId: {} and resourceVersion: {}",
+                                    existingServiceInstanceId, existingResourceVersion);
+                            return true;
+                        }
+                        return false;
+                    });
+
+
+                    return true;
+                }
+
+            }
+        }
+        return false;
+    }
+
+    private ServiceInstances getServiceInstances(final Optional<ServiceSubscription> optional) {
+        final ServiceSubscription serviceSubscription = optional.get();
+        final ServiceInstances serviceInstances = serviceSubscription.getServiceInstances();
+        if (serviceInstances == null) {
+            final ServiceInstances instances = new ServiceInstances();
+            serviceSubscription.setServiceInstances(instances);
+            return instances;
+        }
+        return serviceInstances;
+    }
+
+    @Override
+    public Optional<Relationship> getRelationship(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final String vnfName) {
+        final Optional<ServiceInstance> optional = getServiceInstance(globalCustomerId, serviceType, serviceInstanceId);
+
+        if (optional.isPresent()) {
+            LOGGER.info("Found service instance ...");
+            final ServiceInstance serviceInstance = optional.get();
+            final RelationshipList relationshipList = serviceInstance.getRelationshipList();
+
+            if (relationshipList != null) {
+                final List<Relationship> relationship = relationshipList.getRelationship();
+                return relationship.stream().filter(
+                        relationShip -> relationShip.getRelatedToProperty().stream().filter(relatedToProperty -> {
+                            final String propertyKey = relatedToProperty.getPropertyKey();
+                            final String propertyValue = relatedToProperty.getPropertyValue();
+                            return GENERIC_VNF_VNF_NAME.equals(propertyKey) && propertyValue != null
+                                    && propertyValue.equals(vnfName);
+                        }).findFirst().isPresent()).findFirst();
+            }
+            LOGGER.warn("Relationship list is nulll ...");
+        }
+        LOGGER.error("Unable to RelationShip with property value: {}... ", vnfName);
+
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<Relationship> addRelationShip(final String globalCustomerId, final String serviceType,
+            final String serviceInstanceId, final Relationship relationship, final String requestUri) {
+        final Optional<ServiceInstance> optional = getServiceInstance(globalCustomerId, serviceType, serviceInstanceId);
+        if (optional.isPresent()) {
+            final ServiceInstance serviceInstance = optional.get();
+            RelationshipList relationshipList = serviceInstance.getRelationshipList();
+            if (relationshipList == null) {
+                relationshipList = new RelationshipList();
+                serviceInstance.setRelationshipList(relationshipList);
+            }
+            relationshipList.getRelationship().add(relationship);
+
+            LOGGER.info("Successfully added relation to ServiceInstance");
+
+            final Relationship resultantRelationship = new Relationship();
+            resultantRelationship.setRelatedTo(GENERIC_VNF);
+            resultantRelationship.setRelationshipLabel(relationship.getRelationshipLabel());
+            resultantRelationship.setRelatedLink(getBiDirectionalRelationShipListRelatedLink(requestUri));
+
+            final List<RelationshipData> relationshipDataList = resultantRelationship.getRelationshipData();
+            relationshipDataList.add(getRelationshipData(CUSTOMER_GLOBAL_CUSTOMER_ID, globalCustomerId));
+            relationshipDataList.add(getRelationshipData(SERVICE_SUBSCRIPTION_SERVICE_TYPE, serviceType));
+            relationshipDataList.add(getRelationshipData(SERVICE_INSTANCE_SERVICE_INSTANCE_ID, serviceInstanceId));
+
+            final List<RelatedToProperty> relatedToProperty = resultantRelationship.getRelatedToProperty();
+            relatedToProperty.add(getRelatedToProperty(SERVICE_INSTANCE_SERVICE_INSTANCE_NAME,
+                    serviceInstance.getServiceInstanceName()));
+
+            return Optional.of(resultantRelationship);
+
+        }
+        LOGGER.error("Unable to find ServiceInstance ...");
+        return Optional.empty();
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(CUSTOMER_CACHE.getName());
+    }
+
+    private RelatedToProperty getRelatedToProperty(final String key, final String value) {
+        final RelatedToProperty relatedToProperty = new RelatedToProperty();
+        relatedToProperty.setPropertyKey(key);
+        relatedToProperty.setPropertyValue(value);
+        return relatedToProperty;
+    }
+
+    private RelationshipData getRelationshipData(final String key, final String value) {
+        final RelationshipData relationshipData = new RelationshipData();
+        relationshipData.setRelationshipKey(key);
+        relationshipData.setRelationshipValue(value);
+        return relationshipData;
+    }
+
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ExternalSystemCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ExternalSystemCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..b1f9021
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.List;
+import java.util.Optional;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrSystemInfoList;
+import org.onap.aai.domain.yang.EsrVnfm;
+import org.onap.aai.domain.yang.Relationship;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface ExternalSystemCacheServiceProvider extends Clearable {
+
+    void putEsrVnfm(final String vnfmId, final EsrVnfm esrVnfm);
+
+    Optional<EsrVnfm> getEsrVnfm(final String vnfmId);
+
+    List<EsrVnfm> getAllEsrVnfm();
+
+    Optional<EsrSystemInfoList> getEsrSystemInfoList(final String vnfmId);
+
+    boolean putEsrSystemInfo(final String vnfmId, final String esrSystemInfoId, final EsrSystemInfo esrSystemInfo);
+
+    boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl, final String requestURI,
+            final String vnfmId, Relationship relationship);
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ExternalSystemCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ExternalSystemCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..b5b1da0
--- /dev/null
@@ -0,0 +1,209 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.ESR_VNFM_CACHE;
+import static org.onap.so.aaisimulator.utils.Constants.DEPENDS_ON;
+import static org.onap.so.aaisimulator.utils.Constants.ESR_VNFM;
+import static org.onap.so.aaisimulator.utils.Constants.ESR_VNFM_VNFM_ID;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getRelationShipListRelatedLink;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getTargetUrl;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrSystemInfoList;
+import org.onap.aai.domain.yang.EsrVnfm;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class ExternalSystemCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements ExternalSystemCacheServiceProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ExternalSystemCacheServiceProviderImpl.class);
+
+    private final HttpRestServiceProvider httpRestServiceProvider;
+
+    @Autowired
+    public ExternalSystemCacheServiceProviderImpl(final CacheManager cacheManager,
+            final HttpRestServiceProvider httpRestServiceProvider) {
+        super(cacheManager);
+        this.httpRestServiceProvider = httpRestServiceProvider;
+
+    }
+
+    @Override
+    public void putEsrVnfm(final String vnfmId, final EsrVnfm esrVnfm) {
+        LOGGER.info("Adding esrVnfm: {} with name to cache", esrVnfm);
+        final Cache cache = getCache(ESR_VNFM_CACHE.getName());
+        cache.put(vnfmId, esrVnfm);
+    }
+
+    @Override
+    public Optional<EsrVnfm> getEsrVnfm(final String vnfmId) {
+        LOGGER.info("getting EsrVnfm from cache using key: {}", vnfmId);
+        final Cache cache = getCache(ESR_VNFM_CACHE.getName());
+        final EsrVnfm value = cache.get(vnfmId, EsrVnfm.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        LOGGER.error("Unable to find EsrVnfm in cache using vnfmId: {} ", vnfmId);
+        return Optional.empty();
+    }
+
+    @Override
+    public List<EsrVnfm> getAllEsrVnfm() {
+        final Cache cache = getCache(ESR_VNFM_CACHE.getName());
+        if (cache != null) {
+            final Object nativeCache = cache.getNativeCache();
+            if (nativeCache instanceof ConcurrentHashMap) {
+                @SuppressWarnings("unchecked")
+                final ConcurrentHashMap<Object, Object> concurrentHashMap =
+                        (ConcurrentHashMap<Object, Object>) nativeCache;
+                final List<EsrVnfm> result = new ArrayList<>();
+                concurrentHashMap.keySet().stream().forEach(key -> {
+                    final Optional<EsrVnfm> optional = getEsrVnfm(key.toString());
+                    if (optional.isPresent()) {
+                        result.add(optional.get());
+                    }
+                });
+                return result;
+            }
+        }
+        LOGGER.error("Unable to get all esr vnfms ... ");
+        return Collections.emptyList();
+
+    }
+
+    @Override
+    public Optional<EsrSystemInfoList> getEsrSystemInfoList(final String vnfmId) {
+        final Optional<EsrVnfm> optional = getEsrVnfm(vnfmId);
+        if (optional.isPresent()) {
+            final EsrVnfm esrVnfm = optional.get();
+            if (esrVnfm.getEsrSystemInfoList() != null) {
+                return Optional.of(esrVnfm.getEsrSystemInfoList());
+            }
+            LOGGER.error("EsrSystemInfoList is null for vnfmId: {} ", vnfmId);
+        }
+        LOGGER.error("Unable to find EsrVnfm in cache using vnfmId: {} ", vnfmId);
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean putEsrSystemInfo(final String vnfmId, final String esrSystemInfoId,
+            final EsrSystemInfo esrSystemInfo) {
+        final Optional<EsrVnfm> optional = getEsrVnfm(vnfmId);
+        if (optional.isPresent()) {
+            final EsrVnfm esrVnfm = optional.get();
+            final List<EsrSystemInfo> esrSystemInfoList = getEsrSystemInfoList(esrVnfm);
+
+            final Optional<EsrSystemInfo> existingEsrSystemInfo =
+                    esrSystemInfoList.stream().filter(existing -> existing.getEsrSystemInfoId() != null
+                            && existing.getEsrSystemInfoId().equals(esrSystemInfoId)).findFirst();
+            if (existingEsrSystemInfo.isPresent()) {
+                LOGGER.error("EsrSystemInfo already exists {}", existingEsrSystemInfo.get());
+                return false;
+            }
+
+            return esrSystemInfoList.add(esrSystemInfo);
+        }
+        LOGGER.error("Unable to add EsrSystemInfo in cache for vnfmId: {} ", vnfmId);
+        return false;
+    }
+
+    @Override
+    public boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl,
+            final String requestUriString, final String vnfmId, final Relationship relationship) {
+        try {
+            final Optional<EsrVnfm> optional = getEsrVnfm(vnfmId);
+            if (optional.isPresent()) {
+                final EsrVnfm esrVnfm = optional.get();
+                final String targetUrl = getTargetUrl(targetBaseUrl, relationship.getRelatedLink());
+                final Relationship outGoingRelationShip =
+                        getRelationship(getRelationShipListRelatedLink(requestUriString), esrVnfm);
+                final Optional<Relationship> optionalRelationship = httpRestServiceProvider.put(incomingHeader,
+                        outGoingRelationShip, targetUrl, Relationship.class);
+                if (optionalRelationship.isPresent()) {
+                    final Relationship resultantRelationship = optionalRelationship.get();
+
+                    RelationshipList relationshipList = esrVnfm.getRelationshipList();
+                    if (relationshipList == null) {
+                        relationshipList = new RelationshipList();
+                        esrVnfm.setRelationshipList(relationshipList);
+                    }
+                    if (relationshipList.getRelationship().add(resultantRelationship)) {
+                        LOGGER.info("added relationship {} in cache successfully", resultantRelationship);
+                        return true;
+                    }
+                }
+            }
+        } catch (final Exception exception) {
+            LOGGER.error("Unable to add two-way relationship for vnfmId: {}", vnfmId, exception);
+        }
+        LOGGER.error("Unable to add relationship in cache for vnfmId: {}", vnfmId);
+        return false;
+    }
+
+    private Relationship getRelationship(final String relatedLink, final EsrVnfm esrVnfm) {
+        final Relationship relationShip = new Relationship();
+        relationShip.setRelatedTo(ESR_VNFM);
+        relationShip.setRelationshipLabel(DEPENDS_ON);
+        relationShip.setRelatedLink(relatedLink);
+
+        final RelationshipData relationshipData = new RelationshipData();
+        relationshipData.setRelationshipKey(ESR_VNFM_VNFM_ID);
+        relationshipData.setRelationshipValue(esrVnfm.getVnfmId());
+        relationShip.getRelationshipData().add(relationshipData);
+
+        return relationShip;
+    }
+
+    private List<EsrSystemInfo> getEsrSystemInfoList(final EsrVnfm esrVnfm) {
+        EsrSystemInfoList esrSystemInfoList = esrVnfm.getEsrSystemInfoList();
+        if (esrSystemInfoList == null) {
+            esrSystemInfoList = new EsrSystemInfoList();
+            esrVnfm.setEsrSystemInfoList(esrSystemInfoList);
+        }
+        return esrSystemInfoList.getEsrSystemInfo();
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(ESR_VNFM_CACHE.getName());
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/GenericVnfCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/GenericVnfCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..901c259
--- /dev/null
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.List;
+import java.util.Optional;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.Relationship;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface GenericVnfCacheServiceProvider extends Clearable {
+
+    void putGenericVnf(final String vnfId, final GenericVnf genericVnf);
+
+    Optional<GenericVnf> getGenericVnf(final String vnfId);
+
+    Optional<Relationship> addRelationShip(final String vnfId, final Relationship relationship,
+            final String requestURI);
+
+    boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl, final String requestUriString,
+            final String vnfId, final Relationship relationship);
+
+    Optional<String> getGenericVnfId(final String vnfName);
+
+    boolean patchGenericVnf(final String vnfId, final GenericVnf genericVnf);
+
+    List<GenericVnf> getGenericVnfs(final String selflink);
+
+    boolean deleteGenericVnf(final String vnfId, final String resourceVersion);
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/GenericVnfCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/GenericVnfCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..e7a4210
--- /dev/null
@@ -0,0 +1,258 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.GENERIC_VNF_CACHE;
+import static org.onap.so.aaisimulator.utils.Constants.COMPOSED_OF;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF_VNF_ID;
+import static org.onap.so.aaisimulator.utils.Constants.GENERIC_VNF_VNF_NAME;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getBiDirectionalRelationShipListRelatedLink;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getRelationShipListRelatedLink;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getTargetUrl;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.RelatedToProperty;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.so.aaisimulator.utils.ShallowBeanCopy;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class GenericVnfCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements GenericVnfCacheServiceProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(GenericVnfCacheServiceProviderImpl.class);
+
+    private final HttpRestServiceProvider httpRestServiceProvider;
+
+    @Autowired
+    public GenericVnfCacheServiceProviderImpl(final CacheManager cacheManager,
+            final HttpRestServiceProvider httpRestServiceProvider) {
+        super(cacheManager);
+        this.httpRestServiceProvider = httpRestServiceProvider;
+    }
+
+    @Override
+    public void putGenericVnf(final String vnfId, final GenericVnf genericVnf) {
+        LOGGER.info("Adding customer: {} with key: {} in cache ...", genericVnf, vnfId);
+        final Cache cache = getCache(GENERIC_VNF_CACHE.getName());
+        cache.put(vnfId, genericVnf);
+    }
+
+    @Override
+    public Optional<GenericVnf> getGenericVnf(final String vnfId) {
+        LOGGER.info("getting GenericVnf from cache using key: {}", vnfId);
+        final Cache cache = getCache(GENERIC_VNF_CACHE.getName());
+        final GenericVnf value = cache.get(vnfId, GenericVnf.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        LOGGER.error("Unable to find GenericVnf ...");
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<String> getGenericVnfId(final String vnfName) {
+        final Cache cache = getCache(GENERIC_VNF_CACHE.getName());
+        if (cache != null) {
+            final Object nativeCache = cache.getNativeCache();
+            if (nativeCache instanceof ConcurrentHashMap) {
+                @SuppressWarnings("unchecked")
+                final ConcurrentHashMap<Object, Object> concurrentHashMap =
+                        (ConcurrentHashMap<Object, Object>) nativeCache;
+                for (final Object key : concurrentHashMap.keySet()) {
+                    final Optional<GenericVnf> optional = getGenericVnf(key.toString());
+                    if (optional.isPresent()) {
+                        final GenericVnf value = optional.get();
+                        final String genericVnfName = value.getVnfName();
+                        if (genericVnfName != null && genericVnfName.equals(vnfName)) {
+                            final String genericVnfId = value.getVnfId();
+                            LOGGER.info("Found matching vnf for name: {}, vnf-id: {}", genericVnfName, genericVnfId);
+                            return Optional.of(genericVnfId);
+                        }
+                    }
+                }
+            }
+        }
+        LOGGER.error("No match found for vnf name: {}", vnfName);
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl,
+            final String requestUriString, final String vnfId, final Relationship relationship) {
+        try {
+            final Optional<GenericVnf> optional = getGenericVnf(vnfId);
+            if (optional.isPresent()) {
+                final GenericVnf genericVnf = optional.get();
+                final String targetUrl = getTargetUrl(targetBaseUrl, relationship.getRelatedLink());
+                final Relationship outGoingRelationShip =
+                        getRelationship(getRelationShipListRelatedLink(requestUriString), genericVnf, COMPOSED_OF);
+                final Optional<Relationship> optionalRelationship = httpRestServiceProvider.put(incomingHeader,
+                        outGoingRelationShip, targetUrl, Relationship.class);
+                if (optionalRelationship.isPresent()) {
+                    final Relationship resultantRelationship = optionalRelationship.get();
+
+                    RelationshipList relationshipList = genericVnf.getRelationshipList();
+                    if (relationshipList == null) {
+                        relationshipList = new RelationshipList();
+                        genericVnf.setRelationshipList(relationshipList);
+                    }
+                    if (relationshipList.getRelationship().add(resultantRelationship)) {
+                        LOGGER.info("added relationship {} in cache successfully", resultantRelationship);
+                        return true;
+                    }
+                }
+            }
+        } catch (final Exception exception) {
+            LOGGER.error("Unable to add two-way relationship for vnfId: {}", vnfId, exception);
+        }
+        LOGGER.error("Unable to add relationship in cache for vnfId: {}", vnfId);
+        return false;
+    }
+
+    @Override
+    public Optional<Relationship> addRelationShip(final String vnfId, final Relationship relationship,
+            final String requestURI) {
+        final Optional<GenericVnf> optional = getGenericVnf(vnfId);
+        if (optional.isPresent()) {
+            final GenericVnf genericVnf = optional.get();
+            RelationshipList relationshipList = genericVnf.getRelationshipList();
+            if (relationshipList == null) {
+                relationshipList = new RelationshipList();
+                genericVnf.setRelationshipList(relationshipList);
+            }
+            relationshipList.getRelationship().add(relationship);
+            LOGGER.info("Successfully added relation to GenericVnf for vnfId: {}", vnfId);
+
+            final String relatedLink = getBiDirectionalRelationShipListRelatedLink(requestURI);
+            final Relationship resultantRelationship =
+                    getRelationship(relatedLink, genericVnf, relationship.getRelationshipLabel());
+            return Optional.of(resultantRelationship);
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean patchGenericVnf(final String vnfId, final GenericVnf genericVnf) {
+        final Optional<GenericVnf> optional = getGenericVnf(vnfId);
+        if (optional.isPresent()) {
+            final GenericVnf cachedGenericVnf = optional.get();
+            try {
+                ShallowBeanCopy.copy(genericVnf, cachedGenericVnf);
+                return true;
+            } catch (final Exception exception) {
+                LOGGER.error("Unable to update GenericVnf for vnfId: {}", vnfId, exception);
+            }
+        }
+        LOGGER.error("Unable to find GenericVnf ...");
+        return false;
+    }
+
+    @Override
+    public List<GenericVnf> getGenericVnfs(final String selflink) {
+        final Cache cache = getCache(GENERIC_VNF_CACHE.getName());
+        if (cache != null) {
+            final Object nativeCache = cache.getNativeCache();
+            if (nativeCache instanceof ConcurrentHashMap) {
+                @SuppressWarnings("unchecked")
+                final ConcurrentHashMap<Object, Object> concurrentHashMap =
+                        (ConcurrentHashMap<Object, Object>) nativeCache;
+                final List<GenericVnf> result = new ArrayList<>();
+
+                concurrentHashMap.keySet().stream().forEach(key -> {
+                    final Optional<GenericVnf> optional = getGenericVnf(key.toString());
+                    if (optional.isPresent()) {
+                        final GenericVnf genericVnf = optional.get();
+                        final String genericVnfSelfLink = genericVnf.getSelflink();
+                        final String genericVnfId = genericVnf.getSelflink();
+
+                        if (genericVnfSelfLink != null && genericVnfSelfLink.equals(selflink)) {
+                            LOGGER.info("Found matching vnf for selflink: {}, vnf-id: {}", genericVnfSelfLink,
+                                    genericVnfId);
+                            result.add(genericVnf);
+                        }
+                    }
+                });
+                return result;
+            }
+        }
+        LOGGER.error("No match found for selflink: {}", selflink);
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean deleteGenericVnf(final String vnfId, final String resourceVersion) {
+        final Optional<GenericVnf> optional = getGenericVnf(vnfId);
+        if (optional.isPresent()) {
+            final GenericVnf genericVnf = optional.get();
+            if (genericVnf.getResourceVersion() != null && genericVnf.getResourceVersion().equals(resourceVersion)) {
+                final Cache cache = getCache(GENERIC_VNF_CACHE.getName());
+                LOGGER.info("Will evict GenericVnf from cache with vnfId: {}", genericVnf.getVnfId());
+                cache.evict(vnfId);
+                return true;
+            }
+        }
+        LOGGER.error("Unable to find GenericVnf for vnfId: {} and resourceVersion: {} ...", vnfId, resourceVersion);
+        return false;
+    }
+
+    private Relationship getRelationship(final String relatedLink, final GenericVnf genericVnf,
+            final String relationshipLabel) {
+        final Relationship relationShip = new Relationship();
+        relationShip.setRelatedTo(GENERIC_VNF);
+        relationShip.setRelationshipLabel(relationshipLabel);
+        relationShip.setRelatedLink(relatedLink);
+
+        final RelationshipData relationshipData = new RelationshipData();
+        relationshipData.setRelationshipKey(GENERIC_VNF_VNF_ID);
+        relationshipData.setRelationshipValue(genericVnf.getVnfId());
+        relationShip.getRelationshipData().add(relationshipData);
+
+        final RelatedToProperty relatedToProperty = new RelatedToProperty();
+        relatedToProperty.setPropertyKey(GENERIC_VNF_VNF_NAME);
+        relatedToProperty.setPropertyValue(genericVnf.getVnfName());
+        relationShip.getRelatedToProperty().add(relatedToProperty);
+        return relationShip;
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(GENERIC_VNF_CACHE.getName());
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/HttpRestServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/HttpRestServiceProvider.java
new file mode 100755 (executable)
index 0000000..bbcc435
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface HttpRestServiceProvider {
+
+    <T> ResponseEntity<T> invokeHttpPut(final HttpEntity<Object> httpEntity, final String url, final Class<T> clazz);
+
+    <T> Optional<T> put(final HttpHeaders headers, final Object object, final String url, final Class<T> clazz);
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/HttpRestServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/HttpRestServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..b96920f
--- /dev/null
@@ -0,0 +1,98 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.onap.so.aaisimulator.exception.InvalidRestRequestException;
+import org.onap.so.aaisimulator.exception.RestProcessingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class HttpRestServiceProviderImpl implements HttpRestServiceProvider {
+    private static final Logger LOGGER = LoggerFactory.getLogger(HttpRestServiceProviderImpl.class);
+
+    private final RestTemplate restTemplate;
+
+    @Autowired
+    public HttpRestServiceProviderImpl(final RestTemplate restTemplate) {
+        this.restTemplate = restTemplate;
+    }
+
+    @Override
+    public <T> ResponseEntity<T> invokeHttpPut(final HttpEntity<Object> httpEntity, final String url,
+            final Class<T> clazz) {
+
+        final HttpMethod httpMethod = HttpMethod.PUT;
+        LOGGER.trace("Will invoke HTTP {} using URL: {}", httpMethod, url);
+        try {
+            return restTemplate.exchange(url, httpMethod, httpEntity, clazz);
+
+        } catch (final HttpClientErrorException httpClientErrorException) {
+            final String message = "Unable to invoke HTTP " + httpMethod + " using url: " + url + ", Response: "
+                    + httpClientErrorException.getRawStatusCode();
+            LOGGER.error(message, httpClientErrorException);
+            final int rawStatusCode = httpClientErrorException.getRawStatusCode();
+            if (rawStatusCode == HttpStatus.BAD_REQUEST.value() || rawStatusCode == HttpStatus.NOT_FOUND.value()) {
+                throw new InvalidRestRequestException("No result found for given url: " + url);
+            }
+            throw new RestProcessingException("Unable to invoke HTTP " + httpMethod + " using URL: " + url);
+
+        } catch (final RestClientException restClientException) {
+            LOGGER.error("Unable to invoke HTTP POST using url: {}", url, restClientException);
+            throw new RestProcessingException("Unable to invoke HTTP " + httpMethod + " using URL: " + url,
+                    restClientException);
+        }
+    }
+
+    @Override
+    public <T> Optional<T> put(final HttpHeaders headers, final Object object, final String url, final Class<T> clazz) {
+        final HttpEntity<Object> httpEntity = new HttpEntity<Object>(object, headers);
+        final ResponseEntity<T> response = invokeHttpPut(httpEntity, url, clazz);
+
+        if (!response.getStatusCode().equals(HttpStatus.OK) && !response.getStatusCode().equals(HttpStatus.CREATED)
+                && !response.getStatusCode().equals(HttpStatus.ACCEPTED)) {
+            final String message = "Unable to invoke HTTP " + HttpMethod.PUT + " using URL: " + url
+                    + ", Response Code: " + response.getStatusCode();
+            LOGGER.error(message);
+            return Optional.empty();
+        }
+
+        if (response.hasBody()) {
+            return Optional.of(response.getBody());
+        }
+        LOGGER.error("Received response without body status code: {}", response.getStatusCode());
+        return Optional.empty();
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/LinesOfBusinessCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/LinesOfBusinessCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..dbf5490
--- /dev/null
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.onap.aai.domain.yang.LineOfBusiness;
+import org.onap.aai.domain.yang.Relationship;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface LinesOfBusinessCacheServiceProvider extends Clearable {
+
+    void putLineOfBusiness(final String lineOfBusinessName, final LineOfBusiness lineOfBusiness);
+
+    Optional<LineOfBusiness> getLineOfBusiness(final String lineOfBusinessName);
+
+    Optional<Relationship> addRelationShip(final String lineOfBusinessName, final Relationship relationship,
+            final String requestURI);
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/LinesOfBusinessCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/LinesOfBusinessCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..7614cb6
--- /dev/null
@@ -0,0 +1,111 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.LINES_OF_BUSINESS_CACHE;
+import static org.onap.so.aaisimulator.utils.Constants.LINE_OF_BUSINESS;
+import static org.onap.so.aaisimulator.utils.Constants.LINE_OF_BUSINESS_LINE_OF_BUSINESS_NAME;
+import static org.onap.so.aaisimulator.utils.Constants.USES;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getBiDirectionalRelationShipListRelatedLink;
+import java.util.Optional;
+import org.onap.aai.domain.yang.LineOfBusiness;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class LinesOfBusinessCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements LinesOfBusinessCacheServiceProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(LinesOfBusinessCacheServiceProviderImpl.class);
+
+    @Autowired
+    public LinesOfBusinessCacheServiceProviderImpl(final CacheManager cacheManager) {
+        super(cacheManager);
+    }
+
+    @Override
+    public void putLineOfBusiness(final String lineOfBusinessName, final LineOfBusiness lineOfBusiness) {
+        LOGGER.info("Adding LineOfBusiness to cache with key: {} ...", lineOfBusinessName);
+        final Cache cache = getCache(LINES_OF_BUSINESS_CACHE.getName());
+        cache.put(lineOfBusinessName, lineOfBusiness);
+
+    }
+
+    @Override
+    public Optional<LineOfBusiness> getLineOfBusiness(final String lineOfBusinessName) {
+        LOGGER.info("getting LineOfBusiness from cache using key: {}", lineOfBusinessName);
+        final Cache cache = getCache(LINES_OF_BUSINESS_CACHE.getName());
+        final LineOfBusiness value = cache.get(lineOfBusinessName, LineOfBusiness.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        LOGGER.error("Unable to find LineOfBusiness in cache using key:{} ", lineOfBusinessName);
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<Relationship> addRelationShip(final String lineOfBusinessName, final Relationship relationship,
+            final String requestUri) {
+        final Optional<LineOfBusiness> optional = getLineOfBusiness(lineOfBusinessName);
+        if (optional.isPresent()) {
+            final LineOfBusiness lineOfBusiness = optional.get();
+            RelationshipList relationshipList = lineOfBusiness.getRelationshipList();
+            if (relationshipList == null) {
+                relationshipList = new RelationshipList();
+                lineOfBusiness.setRelationshipList(relationshipList);
+            }
+            relationshipList.getRelationship().add(relationship);
+
+            LOGGER.info("Successfully added relation to LineOfBusiness with name: {}", lineOfBusinessName);
+            final Relationship resultantRelationship = new Relationship();
+            resultantRelationship.setRelatedTo(LINE_OF_BUSINESS);
+            resultantRelationship.setRelationshipLabel(USES);
+            resultantRelationship.setRelatedLink(getBiDirectionalRelationShipListRelatedLink(requestUri));
+
+            final RelationshipData relationshipData = new RelationshipData();
+            relationshipData.setRelationshipKey(LINE_OF_BUSINESS_LINE_OF_BUSINESS_NAME);
+            relationshipData.setRelationshipValue(lineOfBusiness.getLineOfBusinessName());
+            resultantRelationship.getRelationshipData().add(relationshipData);
+
+            return Optional.of(resultantRelationship);
+
+        }
+        LOGGER.error("Unable to find LineOfBusiness using name: {} ...", lineOfBusinessName);
+        return Optional.empty();
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(LINES_OF_BUSINESS_CACHE.getName());
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/NodesCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/NodesCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..0232746
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.onap.aai.domain.yang.GenericVnfs;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.so.aaisimulator.models.NodeServiceInstance;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public interface NodesCacheServiceProvider extends Clearable {
+
+    void putNodeServiceInstance(final String serviceInstanceId, final NodeServiceInstance nodeServiceInstance);
+
+    Optional<NodeServiceInstance> getNodeServiceInstance(final String serviceInstanceId);
+
+    Optional<GenericVnfs> getGenericVnfs(final String vnfName);
+
+    Optional<ServiceInstance> getServiceInstance(final NodeServiceInstance nodeServiceInstance);
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/NodesCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/NodesCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..4ea255f
--- /dev/null
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.NODES_CACHE;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.GenericVnfs;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.so.aaisimulator.models.NodeServiceInstance;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Service
+public class NodesCacheServiceProviderImpl extends AbstractCacheServiceProvider implements NodesCacheServiceProvider {
+    private static final Logger LOGGER = LoggerFactory.getLogger(NodesCacheServiceProviderImpl.class);
+    private final GenericVnfCacheServiceProvider cacheServiceProvider;
+    private final CustomerCacheServiceProvider customerCacheServiceProvider;
+
+
+    @Autowired
+    public NodesCacheServiceProviderImpl(final CacheManager cacheManager,
+            final GenericVnfCacheServiceProvider cacheServiceProvider,
+            final CustomerCacheServiceProvider customerCacheServiceProvider) {
+        super(cacheManager);
+        this.cacheServiceProvider = cacheServiceProvider;
+        this.customerCacheServiceProvider = customerCacheServiceProvider;
+    }
+
+    @Override
+    public void putNodeServiceInstance(final String serviceInstanceId, final NodeServiceInstance nodeServiceInstance) {
+        final Cache cache = getCache(NODES_CACHE.getName());
+        LOGGER.info("Adding {} to cache with key: {}...", nodeServiceInstance, serviceInstanceId);
+        cache.put(serviceInstanceId, nodeServiceInstance);
+    }
+
+    @Override
+    public Optional<NodeServiceInstance> getNodeServiceInstance(final String serviceInstanceId) {
+        final Cache cache = getCache(NODES_CACHE.getName());
+        final NodeServiceInstance value = cache.get(serviceInstanceId, NodeServiceInstance.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        LOGGER.error("Unable to find node service instance in cache using key:{} ", serviceInstanceId);
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<GenericVnfs> getGenericVnfs(final String vnfName) {
+        final Optional<String> genericVnfId = cacheServiceProvider.getGenericVnfId(vnfName);
+        if (genericVnfId.isPresent()) {
+            final Optional<GenericVnf> genericVnf = cacheServiceProvider.getGenericVnf(genericVnfId.get());
+            if (genericVnf.isPresent()) {
+                final GenericVnfs genericVnfs = new GenericVnfs();
+                genericVnfs.getGenericVnf().add(genericVnf.get());
+                return Optional.of(genericVnfs);
+            }
+        }
+        LOGGER.error("Unable to find GenericVnf for name: {}", vnfName);
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<ServiceInstance> getServiceInstance(final NodeServiceInstance nodeServiceInstance) {
+        return customerCacheServiceProvider.getServiceInstance(nodeServiceInstance.getGlobalCustomerId(),
+                nodeServiceInstance.getServiceType(), nodeServiceInstance.getServiceInstanceId());
+    }
+
+    @Override
+    public void clearAll() {
+        final Cache cache = getCache(NODES_CACHE.getName());
+        final ConcurrentHashMap<?, ?> nativeCache = (ConcurrentHashMap<?, ?>) cache.getNativeCache();
+        LOGGER.info("Clear all entries from cahce: {}", cache.getName());
+        nativeCache.clear();
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/OwnEntityCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/OwnEntityCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..394ecf1
--- /dev/null
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.onap.aai.domain.yang.OwningEntity;
+import org.onap.aai.domain.yang.Relationship;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public interface OwnEntityCacheServiceProvider extends Clearable {
+
+    void putOwningEntity(final String owningEntityId, final OwningEntity owningEntity);
+
+    Optional<OwningEntity> getOwningEntity(final String owningEntityId);
+
+    boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl, final String requestUriString,
+            final String owningEntityId, final Relationship relationship);
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/OwnEntityCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/OwnEntityCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..e351c75
--- /dev/null
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.OWNING_ENTITY_CACHE;
+import static org.onap.so.aaisimulator.utils.Constants.BELONGS_TO;
+import static org.onap.so.aaisimulator.utils.Constants.OWNING_ENTITY;
+import static org.onap.so.aaisimulator.utils.Constants.OWNING_ENTITY_OWNING_ENTITY_ID;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getRelationShipListRelatedLink;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getTargetUrl;
+import java.util.List;
+import java.util.Optional;
+import org.onap.aai.domain.yang.OwningEntity;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Service
+public class OwnEntityCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements OwnEntityCacheServiceProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(OwnEntityCacheServiceProviderImpl.class);
+
+    private final HttpRestServiceProvider httpRestServiceProvider;
+
+
+    @Autowired
+    public OwnEntityCacheServiceProviderImpl(final CacheManager cacheManager,
+            final HttpRestServiceProvider httpRestServiceProvider) {
+        super(cacheManager);
+        this.httpRestServiceProvider = httpRestServiceProvider;
+    }
+
+    @Override
+    public void putOwningEntity(final String owningEntityId, final OwningEntity owningEntity) {
+        LOGGER.info("Adding OwningEntity: {} with name to cache", owningEntityId, owningEntity);
+        final Cache cache = getCache(OWNING_ENTITY_CACHE.getName());
+        cache.put(owningEntityId, owningEntity);
+    }
+
+    @Override
+    public Optional<OwningEntity> getOwningEntity(final String owningEntityId) {
+        LOGGER.info("getting OwningEntity from cache using key: {}", owningEntityId);
+        final Cache cache = getCache(OWNING_ENTITY_CACHE.getName());
+        final OwningEntity value = cache.get(owningEntityId, OwningEntity.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl,
+            final String requestUriString, final String owningEntityId, final Relationship relationship) {
+        try {
+            final Optional<OwningEntity> optional = getOwningEntity(owningEntityId);
+            if (optional.isPresent()) {
+                final OwningEntity owningEntity = optional.get();
+                final String targetUrl = getTargetUrl(targetBaseUrl, relationship.getRelatedLink());
+                final Relationship outGoingRelationShip = getRelationship(requestUriString, owningEntity);
+
+                final Optional<Relationship> optionalRelationship = httpRestServiceProvider.put(incomingHeader,
+                        outGoingRelationShip, targetUrl, Relationship.class);
+
+                if (optionalRelationship.isPresent()) {
+                    final Relationship resultantRelationship = optionalRelationship.get();
+
+                    RelationshipList relationshipList = owningEntity.getRelationshipList();
+                    if (relationshipList == null) {
+                        relationshipList = new RelationshipList();
+                        owningEntity.setRelationshipList(relationshipList);
+                    }
+                    if (relationshipList.getRelationship().add(resultantRelationship)) {
+                        LOGGER.info("added relationship {} in cache successfully", resultantRelationship);
+                        return true;
+                    }
+                }
+            }
+
+        } catch (final Exception exception) {
+            LOGGER.error("Unable to add two-way relationship for owning entity id: {}", owningEntityId, exception);
+        }
+        LOGGER.error("Unable to add relationship in cache for owning entity id: {}", owningEntityId);
+        return false;
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(OWNING_ENTITY_CACHE.getName());
+    }
+
+    private Relationship getRelationship(final String requestUriString, final OwningEntity owningEntity) {
+        final Relationship relationShip = new Relationship();
+        relationShip.setRelatedTo(OWNING_ENTITY);
+        relationShip.setRelationshipLabel(BELONGS_TO);
+        relationShip.setRelatedLink(getRelationShipListRelatedLink(requestUriString));
+
+        final List<RelationshipData> relationshipDataList = relationShip.getRelationshipData();
+
+        final RelationshipData relationshipData = new RelationshipData();
+        relationshipData.setRelationshipKey(OWNING_ENTITY_OWNING_ENTITY_ID);
+        relationshipData.setRelationshipValue(owningEntity.getOwningEntityId());
+
+        relationshipDataList.add(relationshipData);
+
+
+        return relationShip;
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PlatformCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PlatformCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..65788bc
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.onap.aai.domain.yang.Platform;
+import org.onap.aai.domain.yang.Relationship;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface PlatformCacheServiceProvider extends Clearable {
+
+    void putPlatform(final String platformName, final Platform platform);
+
+    Optional<Platform> getPlatform(final String platformName);
+
+    Optional<Relationship> addRelationShip(final String platformName, final Relationship relationship,
+            final String requestUri);
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PlatformCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PlatformCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..225885c
--- /dev/null
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.PLATFORM_CACHE;
+import static org.onap.so.aaisimulator.utils.Constants.PLATFORM;
+import static org.onap.so.aaisimulator.utils.Constants.PLATFORM_PLATFORM_NAME;
+import static org.onap.so.aaisimulator.utils.Constants.USES;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getBiDirectionalRelationShipListRelatedLink;
+import java.util.Optional;
+import org.onap.aai.domain.yang.Platform;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class PlatformCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements PlatformCacheServiceProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PlatformCacheServiceProviderImpl.class);
+
+    @Autowired
+    public PlatformCacheServiceProviderImpl(final CacheManager cacheManager) {
+        super(cacheManager);
+    }
+
+    @Override
+    public void putPlatform(final String platformName, final Platform platform) {
+        LOGGER.info("Adding Platform to cache with key: {} ...", platformName);
+        final Cache cache = getCache(PLATFORM_CACHE.getName());
+        cache.put(platformName, platform);
+    }
+
+    @Override
+    public Optional<Platform> getPlatform(final String platformName) {
+        LOGGER.info("getting Platform from cache using key: {}", platformName);
+        final Cache cache = getCache(PLATFORM_CACHE.getName());
+        final Platform value = cache.get(platformName, Platform.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        LOGGER.error("Unable to find Platform in cache using key:{} ", platformName);
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<Relationship> addRelationShip(final String platformName, final Relationship relationship,
+            final String requestUri) {
+        final Optional<Platform> optional = getPlatform(platformName);
+        if (optional.isPresent()) {
+            final Platform platform = optional.get();
+            RelationshipList relationshipList = platform.getRelationshipList();
+            if (relationshipList == null) {
+                relationshipList = new RelationshipList();
+                platform.setRelationshipList(relationshipList);
+            }
+            relationshipList.getRelationship().add(relationship);
+
+            LOGGER.info("Successfully add relation to Platform with name: {}", platformName);
+
+            final Relationship resultantRelationship = new Relationship();
+            resultantRelationship.setRelatedTo(PLATFORM);
+            resultantRelationship.setRelationshipLabel(USES);
+            resultantRelationship.setRelatedLink(getBiDirectionalRelationShipListRelatedLink(requestUri));
+
+            final RelationshipData relationshipData = new RelationshipData();
+            relationshipData.setRelationshipKey(PLATFORM_PLATFORM_NAME);
+            relationshipData.setRelationshipValue(platform.getPlatformName());
+            resultantRelationship.getRelationshipData().add(relationshipData);
+
+            return Optional.of(resultantRelationship);
+        }
+        LOGGER.error("Unable to find Platform ...");
+        return Optional.empty();
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(PLATFORM_CACHE.getName());
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PnfCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PnfCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..89610e0
--- /dev/null
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import org.onap.aai.domain.yang.v15.Pnf;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author Raj Gumma (raj.gumma@est.tech)
+ */
+public interface PnfCacheServiceProvider extends Clearable {
+
+    void putPnf(final String pnfId, final Pnf pnf);
+
+    Optional<Pnf> getPnf(final String pnfId);
+
+    Optional<String> getPnfId(final String pnfName);
+
+    boolean patchPnf(final String pnfId, final Pnf pnf);
+
+    List<Pnf> getPnfs(final String selflink);
+
+    boolean deletePnf(final String pnfId, final String resourceVersion);
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PnfCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PnfCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..cef6c5a
--- /dev/null
@@ -0,0 +1,154 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import org.onap.aai.domain.yang.v15.Pnf;
+import org.onap.so.aaisimulator.utils.ShallowBeanCopy;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.onap.so.aaisimulator.utils.CacheName.PNF_CACHE;
+
+/**
+ * @author Raj Gumma (raj.gumma@est.tech)
+ */
+@Service
+public class PnfCacheServiceProviderImpl extends AbstractCacheServiceProvider implements PnfCacheServiceProvider {
+
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PnfCacheServiceProvider.class);
+
+    private final Cache cache;
+
+    @Autowired
+    public PnfCacheServiceProviderImpl(final CacheManager cacheManager) {
+        super(cacheManager);
+        cache = getCache(PNF_CACHE.getName());
+    }
+
+    @Override
+    public void putPnf(final String pnfId, final Pnf pnf) {
+        LOGGER.info("Adding pnf: {} with key: {} in cache ...", pnf, pnfId);
+        cache.put(pnfId, pnf);
+    }
+
+    @Override
+    public Optional<Pnf> getPnf(final String pnfId) {
+        LOGGER.info("getting Pnf from cache using key: {}", pnfId);
+        final Pnf value = cache.get(pnfId, Pnf.class);
+        return Optional.ofNullable(value);
+    }
+
+    @Override
+    public Optional<String> getPnfId(final String pnfName) {
+        final Object nativeCache = cache.getNativeCache();
+        if (nativeCache instanceof ConcurrentHashMap) {
+            @SuppressWarnings("unchecked") final ConcurrentHashMap<Object, Object> concurrentHashMap =
+                    (ConcurrentHashMap<Object, Object>) nativeCache;
+            for (final Object key : concurrentHashMap.keySet()) {
+                final Optional<Pnf> optional = getPnf(key.toString());
+                if (optional.isPresent()) {
+                    final String cachedPnfName = optional.get().getPnfName();
+                    if (cachedPnfName != null && cachedPnfName.equals(cachedPnfName)) {
+                        final String pnfId = optional.get().getPnfId();
+                        LOGGER.info("Found matching pnf for name: {}, pnf-id: {}", cachedPnfName, pnfId);
+                        return Optional.of(pnfId);
+                    }
+                }
+            }
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean patchPnf(final String pnfId, final Pnf pnf) {
+        final Optional<Pnf> optional = getPnf(pnfId);
+        if (optional.isPresent()) {
+            final Pnf cachedPnf = optional.get();
+            try {
+                ShallowBeanCopy.copy(pnf, cachedPnf);
+                return true;
+            } catch (final Exception exception) {
+                LOGGER.error("Unable to update Pnf for pnfId: {}", pnfId, exception);
+            }
+        }
+        LOGGER.error("Unable to find Pnf for pnfID : {}", pnfId);
+        return false;
+    }
+
+    @Override
+    public List<Pnf> getPnfs(String selfLink) {
+        final Object nativeCache = cache.getNativeCache();
+        if (nativeCache instanceof ConcurrentHashMap) {
+            @SuppressWarnings("unchecked") final ConcurrentHashMap<Object, Object> concurrentHashMap =
+                    (ConcurrentHashMap<Object, Object>) nativeCache;
+            final List<Pnf> result = new ArrayList<>();
+
+            concurrentHashMap.keySet().stream().forEach(key -> {
+                final Optional<Pnf> optional = getPnf(key.toString());
+                if (optional.isPresent()) {
+                    final Pnf pnf = optional.get();
+                    final String pnfSelfLink = pnf.getSelflink();
+                    final String pnfId = pnf.getSelflink();
+
+                    if (pnfSelfLink != null && pnfSelfLink.equals(selfLink)) {
+                        LOGGER.info("Found matching pnf for selflink: {}, pnf-id: {}", pnfSelfLink,
+                                pnfId);
+                        result.add(pnf);
+                    }
+                }
+            });
+            return result;
+        }
+        LOGGER.error("No match found for selflink: {}", selfLink);
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean deletePnf(String pnfId, String resourceVersion) {
+        final Optional<Pnf> optional = getPnf(pnfId);
+        if (optional.isPresent()) {
+            final Pnf pnf = optional.get();
+            if (pnf.getResourceVersion() != null && pnf.getResourceVersion().equals(resourceVersion)) {
+                LOGGER.info("Will evict pnf from cache with pnfId: {}", pnf.getPnfId());
+                cache.evict(pnfId);
+                return true;
+            }
+        }
+        LOGGER.error("Unable to find Pnf for pnfId: {} and resourceVersion: {} ...", pnfId, resourceVersion);
+        return false;
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(cache.getName());
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ProjectCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ProjectCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..9aad53f
--- /dev/null
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import java.util.Optional;
+import org.onap.aai.domain.yang.Project;
+import org.onap.aai.domain.yang.Relationship;
+import org.springframework.http.HttpHeaders;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public interface ProjectCacheServiceProvider extends Clearable {
+
+    void putProject(final String projectName, final Project project);
+
+    Optional<Project> getProject(final String projectName);
+
+    boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl, final String requestUri,
+            final String projectName, final Relationship relationship);
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ProjectCacheServiceProviderImpl.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ProjectCacheServiceProviderImpl.java
new file mode 100755 (executable)
index 0000000..a2eb7ee
--- /dev/null
@@ -0,0 +1,140 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.service.providers;
+
+import static org.onap.so.aaisimulator.utils.CacheName.PROJECT_CACHE;
+import static org.onap.so.aaisimulator.utils.Constants.PROJECT;
+import static org.onap.so.aaisimulator.utils.Constants.PROJECT_PROJECT_NAME;
+import static org.onap.so.aaisimulator.utils.Constants.USES;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getRelationShipListRelatedLink;
+import static org.onap.so.aaisimulator.utils.HttpServiceUtils.getTargetUrl;
+import java.util.List;
+import java.util.Optional;
+import org.onap.aai.domain.yang.Project;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.so.simulator.cache.provider.AbstractCacheServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Service
+public class ProjectCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements ProjectCacheServiceProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ProjectCacheServiceProviderImpl.class);
+
+    private final HttpRestServiceProvider httpRestServiceProvider;
+
+    @Autowired
+    public ProjectCacheServiceProviderImpl(final CacheManager cacheManager,
+            final HttpRestServiceProvider httpRestServiceProvider) {
+        super(cacheManager);
+        this.httpRestServiceProvider = httpRestServiceProvider;
+    }
+
+    @Override
+    public void putProject(final String projectName, final Project project) {
+        LOGGER.info("Adding project: {} with name to cache", project, projectName);
+        final Cache cache = getCache(PROJECT_CACHE.getName());
+        cache.put(projectName, project);
+    }
+
+
+    @Override
+    public Optional<Project> getProject(final String projectName) {
+        LOGGER.info("getting project from cache using key: {}", projectName);
+        final Cache cache = getCache(PROJECT_CACHE.getName());
+        final Project value = cache.get(projectName, Project.class);
+        if (value != null) {
+            return Optional.of(value);
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean addRelationShip(final HttpHeaders incomingHeader, final String targetBaseUrl,
+            final String requestUriString, final String projectName, final Relationship relationship) {
+        try {
+            final Optional<Project> optional = getProject(projectName);
+
+            if (optional.isPresent()) {
+                final Project project = optional.get();
+                final String targetUrl = getTargetUrl(targetBaseUrl, relationship.getRelatedLink());
+                final Relationship outGoingRelationShip = getRelationship(requestUriString, project);
+
+                final Optional<Relationship> optionalRelationship = httpRestServiceProvider.put(incomingHeader,
+                        outGoingRelationShip, targetUrl, Relationship.class);
+
+                if (optionalRelationship.isPresent()) {
+                    final Relationship resultantRelationship = optionalRelationship.get();
+
+                    RelationshipList relationshipList = project.getRelationshipList();
+                    if (relationshipList == null) {
+                        relationshipList = new RelationshipList();
+                        project.setRelationshipList(relationshipList);
+                    }
+                    if (relationshipList.getRelationship().add(resultantRelationship)) {
+                        LOGGER.info("added relationship {} in cache successfully", resultantRelationship);
+                        return true;
+                    }
+                }
+            }
+        } catch (final Exception exception) {
+            LOGGER.error("Unable to add two-way relationship for project name: {}", projectName, exception);
+        }
+        LOGGER.error("Unable to add relationship in cache for project name: {}", projectName);
+        return false;
+    }
+
+    @Override
+    public void clearAll() {
+        clearCache(PROJECT_CACHE.getName());
+    }
+
+    private Relationship getRelationship(final String requestUriString, final Project project) {
+
+        final Relationship relationShip = new Relationship();
+        relationShip.setRelatedTo(PROJECT);
+        relationShip.setRelationshipLabel(USES);
+        relationShip.setRelatedLink(getRelationShipListRelatedLink(requestUriString));
+
+        final List<RelationshipData> relationshipDataList = relationShip.getRelationshipData();
+
+        final RelationshipData relationshipData = new RelationshipData();
+        relationshipData.setRelationshipKey(PROJECT_PROJECT_NAME);
+        relationshipData.setRelationshipValue(project.getProjectName());
+
+        relationshipDataList.add(relationshipData);
+
+
+        return relationShip;
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/CacheName.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/CacheName.java
new file mode 100755 (executable)
index 0000000..f38adcc
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public enum CacheName {
+
+    CUSTOMER_CACHE("customer-cache"),
+    PROJECT_CACHE("project-cache"),
+    NODES_CACHE("nodes-cache"),
+    GENERIC_VNF_CACHE("generic-vnf-cache"),
+    PNF_CACHE("pnf-cache"),
+    OWNING_ENTITY_CACHE("owning-entity-cache"),
+    PLATFORM_CACHE("platform-cache"),
+    LINES_OF_BUSINESS_CACHE("lines-of-business-cache"),
+    CLOUD_REGION_CACHE("cloud-region-cache"),
+    ESR_VNFM_CACHE("esr-vnfm-cache");
+
+    private String name;
+
+    private CacheName(final String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/Constants.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/Constants.java
new file mode 100755 (executable)
index 0000000..230dc13
--- /dev/null
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class Constants {
+
+    public static final String BASE_URL = "/aai/v{version:\\d+}";
+
+    public static final String NODES_URL = BASE_URL + "/nodes";
+
+    public static final String BUSINESS_URL = BASE_URL + "/business";
+
+    public static final String CLOUD_INFRASTRUCTURE_URL = BASE_URL + "/cloud-infrastructure";
+
+    public static final String CLOUD_REGIONS = CLOUD_INFRASTRUCTURE_URL + "/cloud-regions/cloud-region/";
+
+    public static final String CUSTOMER_URL = BUSINESS_URL + "/customers/customer/";
+
+    public static final String PROJECT_URL = BUSINESS_URL + "/projects/project/";
+
+    public static final String OWNING_ENTITY_URL = BUSINESS_URL + "/owning-entities/owning-entity/";
+
+    public static final String PLATFORMS_URL = BUSINESS_URL + "/platforms/platform/";
+
+    public static final String EXTERNAL_SYSTEM_ESR_VNFM_LIST_URL = BASE_URL + "/external-system/esr-vnfm-list";
+
+    public static final String NETWORK_URL = BASE_URL + "/network";
+
+    public static final String GENERIC_VNFS_URL = NETWORK_URL + "/generic-vnfs";
+
+    public static final String PNFS_URL = NETWORK_URL+ "/pnfs";
+
+    public static final String RELATIONSHIP_LIST_RELATIONSHIP_URL = "/relationship-list/relationship";
+
+    public static final String BI_DIRECTIONAL_RELATIONSHIP_LIST_URL =
+            RELATIONSHIP_LIST_RELATIONSHIP_URL + "/bi-directional";
+
+    public static final String LINES_OF_BUSINESS_URL = BUSINESS_URL + "/lines-of-business/line-of-business/";
+
+    public static final String HEALTHY = "healthy";
+
+    public static final String PROJECT = "project";
+
+    public static final String PROJECT_PROJECT_NAME = "project.project-name";
+
+    public static final String OWNING_ENTITY = "owning-entity";
+
+    public static final String OWNING_ENTITY_OWNING_ENTITY_ID = "owning-entity.owning-entity-id";
+
+    public static final String X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
+
+    public static final String APPLICATION_MERGE_PATCH_JSON = "application/merge-patch+json";
+
+    public static final String SERVICE_RESOURCE_TYPE = "service-instance";
+
+    public static final String RESOURCE_LINK = "resource-link";
+
+    public static final String RESOURCE_TYPE = "resource-type";
+
+    public static final String GENERIC_VNF_VNF_NAME = "generic-vnf.vnf-name";
+
+    public static final String GENERIC_VNF_VNF_ID = "generic-vnf.vnf-id";
+
+    public static final String SERVICE_INSTANCE_SERVICE_INSTANCE_ID = "service-instance.service-instance-id";
+
+    public static final String SERVICE_SUBSCRIPTION_SERVICE_TYPE = "service-subscription.service-type";
+
+    public static final String CUSTOMER_GLOBAL_CUSTOMER_ID = "customer.global-customer-id";
+
+    public static final String COMPOSED_OF = "org.onap.relationships.inventory.ComposedOf";
+
+    public static final String GENERIC_VNF = "generic-vnf";
+
+    public static final String PNF = "pnf";
+
+    public static final String PLATFORM = "platform";
+
+    public static final String USES = "org.onap.relationships.inventory.Uses";
+
+    public static final String PLATFORM_PLATFORM_NAME = "platform.platform-name";
+
+    public static final String LINE_OF_BUSINESS_LINE_OF_BUSINESS_NAME = "line-of-business.line-of-business-name";
+
+    public static final String LINE_OF_BUSINESS = "line-of-business";
+
+    public static final String SERVICE_SUBSCRIPTION = "service-subscription";
+
+    public static final String CUSTOMER_TYPE = "Customer";
+
+    public static final String SERVICE_INSTANCE_SERVICE_INSTANCE_NAME = "service-instance.service-instance-name";
+
+    public static final String CLOUD_REGION_OWNER_DEFINED_TYPE = "cloud-region.owner-defined-type";
+
+    public static final String CLOUD_REGION_CLOUD_REGION_ID = "cloud-region.cloud-region-id";
+
+    public static final String CLOUD_REGION_CLOUD_OWNER = "cloud-region.cloud-owner";
+
+    public static final String LOCATED_IN = "org.onap.relationships.inventory.LocatedIn";
+
+    public static final String CLOUD_REGION = "cloud-region";
+
+    public static final String TENANT_TENANT_NAME = "tenant.tenant-name";
+
+    public static final String TENANT_TENANT_ID = "tenant.tenant-id";
+
+    public static final String BELONGS_TO = "org.onap.relationships.inventory.BelongsTo";
+
+    public static final String TENANT = "tenant";
+
+    public static final String ESR_VNFM = "esr-vnfm";
+
+    public static final String ESR_SYSTEM_INFO = "esr-system-info";
+
+    public static final String ESR_SYSTEM_INFO_LIST = "esr-system-info-list";
+
+    public static final String ESR_VNFM_VNFM_ID = "esr-vnfm.vnfm-id";
+
+    public static final String DEPENDS_ON = "tosca.relationships.DependsOn";
+
+    public static final String VSERVER_VSERVER_NAME = "vserver.vserver-name";
+
+    public static final String VSERVER_VSERVER_ID = "vserver.vserver-id";
+
+    public static final String HOSTED_ON = "tosca.relationships.HostedOn";
+
+    public static final String VSERVER = "vserver";
+
+    private Constants() {}
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/HttpServiceUtils.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/HttpServiceUtils.java
new file mode 100755 (executable)
index 0000000..8178102
--- /dev/null
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.springframework.http.MediaType.APPLICATION_XML;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.web.util.UriComponentsBuilder;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class HttpServiceUtils {
+
+    private static final String START_WITH_FORWARD_SLASH = "(^/.*?)";
+    private static final String ALPHANUMERIC = "((?:v+[a-z0-9]*)/)";
+    private static final String REGEX = START_WITH_FORWARD_SLASH + ALPHANUMERIC;
+    private static final Pattern PATTERN = Pattern.compile(REGEX, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
+
+    private HttpServiceUtils() {}
+
+    public static URI getBaseUrl(final HttpServletRequest request) {
+        final StringBuffer url = request.getRequestURL();
+        final String uri = request.getRequestURI();
+        return UriComponentsBuilder.fromHttpUrl(url.substring(0, url.indexOf(uri))).path(getBaseUrl(uri)).build()
+                .toUri();
+    }
+
+    private static String getBaseUrl(final String uri) {
+        final Matcher matcher = PATTERN.matcher(uri);
+        if (matcher.find()) {
+            final StringBuilder builder = new StringBuilder();
+            for (int index = 0; index < matcher.groupCount() - 1; index++) {
+                builder.append(matcher.group(index));
+            }
+            return builder.toString();
+        }
+        return uri;
+    }
+
+    public static URI getBaseUrl(final StringBuffer requestUrl, final String requestUri) {
+        return UriComponentsBuilder.fromHttpUrl(requestUrl.substring(0, requestUrl.indexOf(requestUri))).build()
+                .toUri();
+    }
+
+    public static String getBaseServiceInstanceUrl(final HttpServletRequest request, final String relatedLink) {
+        return UriComponentsBuilder.fromUri(getBaseUrl(request)).path(relatedLink).toUriString();
+    }
+
+    public static HttpHeaders getHeaders(final HttpServletRequest request) {
+        return getHeaders(request, APPLICATION_XML);
+    }
+
+    public static HttpHeaders getHeaders(final HttpServletRequest request, final MediaType mediaType) {
+        final HttpHeaders headers = new HttpHeaders();
+        for (final Enumeration<String> enumeration = request.getHeaderNames(); enumeration.hasMoreElements();) {
+            final String headerName = enumeration.nextElement();
+            headers.add(headerName, request.getHeader(headerName));
+        }
+        headers.setContentType(mediaType);
+        headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
+        return headers;
+    }
+
+    public static String getTargetUrl(final String targetBaseUrl, final String relatedLink) {
+        return UriComponentsBuilder.fromUriString(targetBaseUrl).path(relatedLink)
+                .path(BI_DIRECTIONAL_RELATIONSHIP_LIST_URL).toUriString();
+    }
+
+    public static String getRelationShipListRelatedLink(final String requestUriString) {
+        return requestUriString != null ? requestUriString.replaceFirst(RELATIONSHIP_LIST_RELATIONSHIP_URL, "")
+                : requestUriString;
+    }
+
+    public static String getBiDirectionalRelationShipListRelatedLink(final String requestUriString) {
+        return requestUriString != null ? requestUriString.replaceFirst(BI_DIRECTIONAL_RELATIONSHIP_LIST_URL, "")
+                : requestUriString;
+    }
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestError.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestError.java
new file mode 100755 (executable)
index 0000000..782625f
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@XmlRootElement(name = "requestError")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RequestError {
+
+    @XmlElement(name = "serviceException")
+    private ServiceException serviceException;
+
+    /**
+     * @return the serviceException
+     */
+    public ServiceException getServiceException() {
+        return serviceException;
+    }
+
+    /**
+     * @param serviceException the serviceException to set
+     */
+    public void setServiceException(final ServiceException serviceException) {
+        this.serviceException = serviceException;
+    }
+
+    @Override
+    public String toString() {
+        return "RequestError [serviceException=" + serviceException + "]";
+    }
+
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestErrorBuilder.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestErrorBuilder.java
new file mode 100755 (executable)
index 0000000..f374222
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class RequestErrorBuilder {
+
+    private final ServiceException serviceException = new ServiceException();
+
+    public RequestErrorBuilder messageId(final String messageId) {
+        this.serviceException.setMessageId(messageId);
+        return this;
+    }
+
+    public RequestErrorBuilder text(final String text) {
+        this.serviceException.setText(text);
+        return this;
+    }
+
+    public RequestErrorBuilder variables(final List<String> variables) {
+        this.serviceException.setVariables(variables);
+        return this;
+    }
+
+    public RequestErrorBuilder variables(final String... variables) {
+        this.serviceException.setVariables(Arrays.asList(variables));
+        return this;
+    }
+
+    public RequestError build() {
+        final RequestError requestError = new RequestError();
+        requestError.setServiceException(serviceException);
+        return requestError;
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestErrorResponseUtils.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestErrorResponseUtils.java
new file mode 100755 (executable)
index 0000000..755d3a7
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class RequestErrorResponseUtils {
+
+    public static final String ERROR_MESSAGE_ID = "SVC3001";
+
+    public static final String ERROR_MESSAGE = "Resource not found for %1 using id %2 (msg=%3) (ec=%4)";
+
+    private static final String EMPTY_STRING = "";
+
+    public static final String getResourceVersion() {
+        return System.currentTimeMillis() + EMPTY_STRING;
+    }
+
+    public static ResponseEntity<?> getRequestErrorResponseEntity(final HttpServletRequest request,
+            final String nodeType) {
+        return new ResponseEntity<>(new RequestErrorBuilder().messageId(ERROR_MESSAGE_ID).text(ERROR_MESSAGE)
+                .variables(request.getMethod(), request.getRequestURI(),
+                        "Node Not Found:No Node of " + nodeType + " found at: " + request.getRequestURI(),
+                        "ERR.5.4.6114")
+                .build(), HttpStatus.NOT_FOUND);
+    }
+
+    public static ResponseEntity<?> getRequestErrorResponseEntity(final HttpServletRequest request) {
+        return getRequestErrorResponseEntity(request, Constants.SERVICE_RESOURCE_TYPE);
+    }
+
+    private RequestErrorResponseUtils() {}
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/ServiceException.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/ServiceException.java
new file mode 100755 (executable)
index 0000000..7ba47fa
--- /dev/null
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@XmlRootElement(name = "serviceException")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceException {
+
+    private String messageId;
+
+    private String text;
+
+    private List<String> variables;
+
+    /**
+     * @return the messageId
+     */
+    public String getMessageId() {
+        return messageId;
+    }
+
+    /**
+     * @param messageId the messageId to set
+     */
+    public void setMessageId(final String messageId) {
+        this.messageId = messageId;
+    }
+
+    /**
+     * @return the text
+     */
+    public String getText() {
+        return text;
+    }
+
+    /**
+     * @param text the text to set
+     */
+    public void setText(final String text) {
+        this.text = text;
+    }
+
+    /**
+     * @return the variables
+     */
+    public List<String> getVariables() {
+        return variables;
+    }
+
+    /**
+     * @param variables the variables to set
+     */
+    public void setVariables(final List<String> variables) {
+        this.variables = variables;
+    }
+
+    @Override
+    public String toString() {
+        return "ServiceException [messageId=" + messageId + ", text=" + text + ", variables=" + variables + "]";
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/ShallowBeanCopy.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/ShallowBeanCopy.java
new file mode 100755 (executable)
index 0000000..3285e01
--- /dev/null
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class ShallowBeanCopy {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ShallowBeanCopy.class);
+
+    private ShallowBeanCopy() {}
+
+    public static void copy(final Object from, final Object to) throws Exception {
+        final Map<String, Method> fromMethods = getMethods(from);
+        final Map<String, Method> toMethods = getMethods(to);
+
+        for (final Entry<String, Method> entry : fromMethods.entrySet()) {
+            final String methodName = entry.getKey();
+            final Method fromMethod = entry.getValue();
+
+            final Optional<Method> optional = getSetMethod(to, fromMethod);
+            if (optional.isPresent()) {
+                final Method toGetMethod = toMethods.get(methodName);
+                final Method toMethod = optional.get();
+                final Object toValue = fromMethod.invoke(from);
+
+                final Object fromValue = toGetMethod.invoke(to);
+                if (toValue != null && !toValue.equals(fromValue)) {
+                    LOGGER.info("Changing {} value from: {} to: {}", methodName, fromValue, toValue);
+                    toMethod.invoke(to, toValue);
+                }
+            }
+        }
+    }
+
+
+    private static Optional<Method> getSetMethod(final Object to, final Method fromMethod) {
+        final String name = fromMethod.getName().replaceFirst("get|is", "set");
+        final Class<?> returnType = fromMethod.getReturnType();
+        try {
+            return Optional.of(to.getClass().getMethod(name, returnType));
+        } catch (final NoSuchMethodException noSuchMethodException) {
+        }
+        return Optional.empty();
+    }
+
+    private static Map<String, Method> getMethods(final Object object) {
+        final Map<String, Method> methodsFound = new HashMap<>();
+        final Method[] methods = object.getClass().getMethods();
+
+        for (final Method method : methods) {
+            if (method.getName().startsWith("get") || method.getName().startsWith("is")) {
+                final String name = method.getName().replaceFirst("get|is", "");
+
+                methodsFound.put(name, method);
+            }
+        }
+
+        return methodsFound;
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/application.yaml b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/application.yaml
new file mode 100755 (executable)
index 0000000..205abe4
--- /dev/null
@@ -0,0 +1,25 @@
+server:
+   port: 9993
+   tomcat:
+      max-threads: 4
+   ssl:
+      key-store: classpath:keystore/org.onap.so.p12
+      key-store-password: u!@JQoYD])@ykq.NKM,O7iA.
+      keyStoreType: PKCS12
+ssl-enable: true
+spring:
+   security:
+      users:
+      -  username: aai
+         #password: aai.onap.org:demo123456!
+         password: $2a$04$crRntT01fAF4kb48mxlvgu68/silcLg.czC1LxQsKTdWuDBPpO3YO
+         role: VID
+      -  username: aai@aai.onap.org
+         #password: demo123456!
+         password: $2a$04$06VCpDvW5ztE7WOvhhvAtOx7JHLghECyZIzOShIbXLWpnshMva8T6
+         role: VID
+http:
+   client:
+      ssl:
+         trust-store: classpath:truststore/org.onap.so.trust.jks
+         trust-store-password: '[)3KV.k*!IlkFhWEq0Nv2dDa'
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/keystore/org.onap.so.p12 b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/keystore/org.onap.so.p12
new file mode 100755 (executable)
index 0000000..015f2bf
Binary files /dev/null and b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/keystore/org.onap.so.p12 differ
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/truststore/org.onap.so.trust.jks b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/truststore/org.onap.so.trust.jks
new file mode 100755 (executable)
index 0000000..88d6184
Binary files /dev/null and b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/truststore/org.onap.so.trust.jks differ
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/AaiSimulatorControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/AaiSimulatorControllerTest.java
new file mode 100755 (executable)
index 0000000..4fe5c40
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.aaisimulator.utils.TestConstants;
+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.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ActiveProfiles("test")
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+@Configuration
+public class AaiSimulatorControllerTest {
+
+    @LocalServerPort
+    private int port;
+
+    @Autowired
+    private TestRestTemplate restTemplate;
+
+    @Test
+    public void test_healthCheck_matchContent() {
+        final String url = getBaseUrl() + "/healthcheck";
+        final ResponseEntity<String> object = restTemplate.getForEntity(url, String.class);
+
+        assertEquals(Constants.HEALTHY, object.getBody());
+    }
+
+    private String getBaseUrl() {
+        return "https://localhost:" + port + TestConstants.BASE_URL_V17;
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/AbstractSpringBootTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/AbstractSpringBootTest.java
new file mode 100755 (executable)
index 0000000..84bb8ca
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import java.util.List;
+import org.junit.runner.RunWith;
+import org.onap.aai.domain.yang.RelatedToProperty;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.so.aaisimulator.utils.TestRestTemplateService;
+import org.onap.so.aaisimulator.utils.TestUtils;
+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.boot.web.server.LocalServerPort;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ActiveProfiles("test")
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+@Configuration
+public abstract class AbstractSpringBootTest {
+
+    @LocalServerPort
+    private int port;
+
+    @Autowired
+    protected TestRestTemplateService testRestTemplateService;
+
+    public String getUrl(final String... urls) {
+        return TestUtils.getUrl(port, urls);
+    }
+
+    public RelationshipData getRelationshipData(final List<RelationshipData> relationshipData, final String key) {
+        return relationshipData.stream().filter(data -> data.getRelationshipKey().equals(key)).findFirst().orElse(null);
+    }
+
+    public RelatedToProperty getRelatedToProperty(final List<RelatedToProperty> relatedToPropertyList,
+            final String key) {
+        return relatedToPropertyList.stream().filter(data -> data.getPropertyKey().equals(key)).findFirst()
+                .orElse(null);
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/BusinessControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/BusinessControllerTest.java
new file mode 100755 (executable)
index 0000000..c08c51e
--- /dev/null
@@ -0,0 +1,397 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.X_HTTP_METHOD_OVERRIDE;
+import static org.onap.so.aaisimulator.utils.TestConstants.CUSTOMERS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GLOBAL_CUSTOMER_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.RELATED_TO_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCES_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_SUBSCRIPTIONS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_TYPE;
+import static org.onap.so.aaisimulator.utils.TestConstants.VNF_ID;
+import static org.onap.so.aaisimulator.utils.TestUtils.getCustomer;
+import static org.onap.so.aaisimulator.utils.TestUtils.getServiceInstance;
+import java.io.IOException;
+import java.util.Optional;
+import java.util.UUID;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.Customer;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.GenericVnfs;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.aai.domain.yang.ServiceInstances;
+import org.onap.aai.domain.yang.ServiceSubscription;
+import org.onap.so.aaisimulator.service.providers.CustomerCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.RequestError;
+import org.onap.so.aaisimulator.utils.RequestErrorResponseUtils;
+import org.onap.so.aaisimulator.utils.ServiceException;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class BusinessControllerTest extends AbstractSpringBootTest {
+
+    private static final String FIREWALL_SERVICE_TYPE = "Firewall";
+
+    private static final String ORCHESTRATION_STATUS = "Active";
+
+    @Autowired
+    private CustomerCacheServiceProvider cacheServiceProvider;
+
+    @After
+    public void after() {
+        cacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_putCustomer_successfullyAddedToCache() throws Exception {
+        invokeCustomerEndPointAndAssertResponse();
+        assertTrue(cacheServiceProvider.getCustomer(GLOBAL_CUSTOMER_ID).isPresent());
+    }
+
+    @Test
+    public void test_getCustomer_ableToRetrieveCustomer() throws Exception {
+        final String url = getUrl(CUSTOMERS_URL);
+
+        final ResponseEntity<Void> response = testRestTemplateService.invokeHttpPut(url, getCustomer(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+
+        final ResponseEntity<Customer> actual = testRestTemplateService.invokeHttpGet(url, Customer.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final Customer actualCustomer = actual.getBody();
+        assertEquals(GLOBAL_CUSTOMER_ID, actualCustomer.getGlobalCustomerId());
+        assertNotNull(actualCustomer.getResourceVersion());
+        assertFalse(actualCustomer.getResourceVersion().isEmpty());
+    }
+
+    @Test
+    public void test_getCustomer_returnRequestError_ifCustomerNotInCache() throws Exception {
+        final String url = getUrl(CUSTOMERS_URL);
+
+        final ResponseEntity<RequestError> actual = testRestTemplateService.invokeHttpGet(url, RequestError.class);
+
+        assertEquals(HttpStatus.NOT_FOUND, actual.getStatusCode());
+
+        final RequestError actualError = actual.getBody();
+        final ServiceException serviceException = actualError.getServiceException();
+
+        assertNotNull(serviceException);
+        assertEquals(RequestErrorResponseUtils.ERROR_MESSAGE_ID, serviceException.getMessageId());
+        assertEquals(RequestErrorResponseUtils.ERROR_MESSAGE, serviceException.getText());
+        assertTrue(serviceException.getVariables().contains(HttpMethod.GET.toString()));
+
+    }
+
+    @Test
+    public void test_getServiceSubscription_ableToRetrieveServiceSubscriptionFromCache() throws Exception {
+        final String url = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL);
+
+        invokeCustomerEndPointAndAssertResponse();
+
+        final ResponseEntity<ServiceSubscription> actual =
+                testRestTemplateService.invokeHttpGet(url, ServiceSubscription.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final ServiceSubscription actualServiceSubscription = actual.getBody();
+        assertEquals(SERVICE_TYPE, actualServiceSubscription.getServiceType());
+        assertNotNull(actualServiceSubscription.getRelationshipList());
+        assertFalse(actualServiceSubscription.getRelationshipList().getRelationship().isEmpty());
+    }
+
+    @Test
+    public void test_putSericeInstance_ableToRetrieveServiceInstanceFromCache() throws Exception {
+
+        invokeCustomerEndPointAndAssertResponse();
+        invokeServiceInstanceEndPointAndAssertResponse();
+
+
+        final Optional<ServiceInstance> actual =
+                cacheServiceProvider.getServiceInstance(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, SERVICE_INSTANCE_ID);
+
+        assertTrue(actual.isPresent());
+        final ServiceInstance actualServiceInstance = actual.get();
+
+        assertEquals(SERVICE_INSTANCE_ID, actualServiceInstance.getServiceInstanceId());
+        assertEquals(SERVICE_NAME, actualServiceInstance.getServiceInstanceName());
+
+    }
+
+    @Test
+    public void test_getSericeInstance_usingServiceInstanceName_ableToRetrieveServiceInstanceFromCache()
+            throws Exception {
+
+        invokeCustomerEndPointAndAssertResponse();
+        invokeServiceInstanceEndPointAndAssertResponse();
+
+
+        final String serviceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCES_URL)
+                + "?depth=2&service-instance-name=" + SERVICE_NAME;
+
+        final ResponseEntity<ServiceInstances> actual =
+                testRestTemplateService.invokeHttpGet(serviceInstanceUrl, ServiceInstances.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final ServiceInstances actualServiceInstances = actual.getBody();
+        assertFalse(actualServiceInstances.getServiceInstance().isEmpty());
+
+        assertEquals(SERVICE_NAME, actualServiceInstances.getServiceInstance().get(0).getServiceInstanceName());
+
+    }
+
+    @Test
+    public void test_getSericeInstance_usingServiceInstanceName_returnRequestErrorIfnoServiceInstanceFound()
+            throws Exception {
+
+        invokeCustomerEndPointAndAssertResponse();
+
+        final String serviceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCES_URL)
+                + "?depth=2&service-instance-name=" + SERVICE_NAME;
+
+        final ResponseEntity<RequestError> actual =
+                testRestTemplateService.invokeHttpGet(serviceInstanceUrl, RequestError.class);
+
+        assertEquals(HttpStatus.NOT_FOUND, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        assertNotNull(actual.getBody().getServiceException());
+
+    }
+
+    @Test
+    public void test_getSericeInstance_usingServiceInstanceId_ableToRetrieveServiceInstanceFromCache()
+            throws Exception {
+
+        final String url = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+
+        invokeCustomerEndPointAndAssertResponse();
+        invokeServiceInstanceEndPointAndAssertResponse();
+
+        final ResponseEntity<ServiceInstance> actual =
+                testRestTemplateService.invokeHttpGet(url, ServiceInstance.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final ServiceInstance actualServiceInstance = actual.getBody();
+
+        assertEquals(SERVICE_NAME, actualServiceInstance.getServiceInstanceName());
+        assertEquals(SERVICE_INSTANCE_ID, actualServiceInstance.getServiceInstanceId());
+
+    }
+
+    @Test
+    public void test_getSericeInstance_usinginvalidServiceInstanceId_shouldReturnError() throws Exception {
+
+        invokeCustomerEndPointAndAssertResponse();
+
+        invokeServiceInstanceEndPointAndAssertResponse();
+
+
+        final String invalidServiceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL,
+                SERVICE_INSTANCES_URL + "/service-instance/" + UUID.randomUUID());
+
+        final ResponseEntity<RequestError> actual =
+                testRestTemplateService.invokeHttpGet(invalidServiceInstanceUrl, RequestError.class);
+
+        assertEquals(HttpStatus.NOT_FOUND, actual.getStatusCode());
+
+        final RequestError actualError = actual.getBody();
+        final ServiceException serviceException = actualError.getServiceException();
+
+        assertNotNull(serviceException);
+        assertEquals(RequestErrorResponseUtils.ERROR_MESSAGE_ID, serviceException.getMessageId());
+        assertEquals(RequestErrorResponseUtils.ERROR_MESSAGE, serviceException.getText());
+        assertTrue(serviceException.getVariables().contains(HttpMethod.GET.toString()));
+
+    }
+
+    @Test
+    public void test_getSericeInstance_usingInvalidServiceInstanceName_shouldReturnError() throws Exception {
+
+        invokeCustomerEndPointAndAssertResponse();
+        invokeServiceInstanceEndPointAndAssertResponse();
+
+
+        final String serviceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCES_URL)
+                + "?service-instance-name=Dummy&depth=2";
+
+        final ResponseEntity<RequestError> actual =
+                testRestTemplateService.invokeHttpGet(serviceInstanceUrl, RequestError.class);
+
+        assertEquals(HttpStatus.NOT_FOUND, actual.getStatusCode());
+
+        final RequestError actualError = actual.getBody();
+        final ServiceException serviceException = actualError.getServiceException();
+
+        assertNotNull(serviceException);
+        assertEquals(RequestErrorResponseUtils.ERROR_MESSAGE_ID, serviceException.getMessageId());
+        assertEquals(RequestErrorResponseUtils.ERROR_MESSAGE, serviceException.getText());
+        assertTrue(serviceException.getVariables().contains(HttpMethod.GET.toString()));
+
+    }
+
+    @Test
+    public void test_PathSericeInstance_usingServiceInstanceId_OrchStatusChangedInCache() throws Exception {
+
+        final String url = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+
+        invokeCustomerEndPointAndAssertResponse();
+        invokeServiceInstanceEndPointAndAssertResponse();
+
+        final HttpHeaders httpHeaders = testRestTemplateService.getHttpHeaders();
+        httpHeaders.add(X_HTTP_METHOD_OVERRIDE, HttpMethod.PATCH.toString());
+
+        final ResponseEntity<Void> orchStatuUpdateServiceInstanceResponse = testRestTemplateService
+                .invokeHttpPost(httpHeaders, url, TestUtils.getOrchStatuUpdateServiceInstance(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, orchStatuUpdateServiceInstanceResponse.getStatusCode());
+
+        final ResponseEntity<ServiceInstance> actual =
+                testRestTemplateService.invokeHttpGet(url, ServiceInstance.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final ServiceInstance actualServiceInstance = actual.getBody();
+
+        assertEquals(SERVICE_NAME, actualServiceInstance.getServiceInstanceName());
+        assertEquals(SERVICE_INSTANCE_ID, actualServiceInstance.getServiceInstanceId());
+        assertEquals(ORCHESTRATION_STATUS, actualServiceInstance.getOrchestrationStatus());
+
+    }
+
+    @Test
+    public void test_putServiceSubscription_successfullyAddedToCache() throws Exception {
+        final String serviceSubscriptionurl =
+                getUrl(CUSTOMERS_URL, "/service-subscriptions/service-subscription/", FIREWALL_SERVICE_TYPE);
+
+        invokeCustomerEndPointAndAssertResponse();
+
+        final ResponseEntity<Void> responseEntity = testRestTemplateService.invokeHttpPut(serviceSubscriptionurl,
+                TestUtils.getServiceSubscription(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+
+        final ResponseEntity<ServiceSubscription> actual =
+                testRestTemplateService.invokeHttpGet(serviceSubscriptionurl, ServiceSubscription.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final ServiceSubscription actualServiceSubscription = actual.getBody();
+        assertEquals(FIREWALL_SERVICE_TYPE, actualServiceSubscription.getServiceType());
+
+    }
+
+    @Test
+    public void test_putSericeInstanceRelatedTo_ableToRetrieveServiceInstanceFromCache() throws Exception {
+
+        final String url = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+
+        invokeCustomerEndPointAndAssertResponse();
+
+        invokeServiceInstanceEndPointAndAssertResponse();
+
+        final String relationShipUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL,
+                BI_DIRECTIONAL_RELATIONSHIP_LIST_URL);
+
+        final ResponseEntity<Relationship> responseEntity2 = testRestTemplateService.invokeHttpPut(relationShipUrl,
+                TestUtils.getRelationShipJsonObject(), Relationship.class);
+
+        assertEquals(HttpStatus.ACCEPTED, responseEntity2.getStatusCode());
+
+        final String genericVnfUrl = getUrl(GENERIC_VNF_URL, VNF_ID);
+        final ResponseEntity<Void> genericVnfResponse =
+                testRestTemplateService.invokeHttpPut(genericVnfUrl, TestUtils.getGenericVnf(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, genericVnfResponse.getStatusCode());
+
+        final ResponseEntity<GenericVnfs> actual = testRestTemplateService
+                .invokeHttpGet(url + RELATED_TO_URL + "?vnf-name=" + GENERIC_VNF_NAME, GenericVnfs.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+
+        assertTrue(actual.hasBody());
+        final GenericVnfs genericVnfs = actual.getBody();
+        assertFalse(genericVnfs.getGenericVnf().isEmpty());
+        final GenericVnf genericVnf = genericVnfs.getGenericVnf().get(0);
+        assertEquals(GENERIC_VNF_NAME, genericVnf.getVnfName());
+    }
+
+    @Test
+    public void test_DeleteSericeInstance_ServiceInstanceRemovedFromCache() throws Exception {
+        final String url = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+
+        invokeCustomerEndPointAndAssertResponse();
+
+        invokeServiceInstanceEndPointAndAssertResponse();
+
+        final Optional<ServiceInstance> optional =
+                cacheServiceProvider.getServiceInstance(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, SERVICE_INSTANCE_ID);
+        assertTrue(optional.isPresent());
+        final ServiceInstance serviceInstance = optional.get();
+
+        final ResponseEntity<Void> responseEntity = testRestTemplateService
+                .invokeHttpDelete(url + "?resource-version=" + serviceInstance.getResourceVersion(), Void.class);
+        assertEquals(HttpStatus.NO_CONTENT, responseEntity.getStatusCode());
+        assertFalse(cacheServiceProvider.getServiceInstance(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, SERVICE_INSTANCE_ID)
+                .isPresent());
+    }
+
+    private void invokeServiceInstanceEndPointAndAssertResponse() throws IOException {
+        final String url = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+        final ResponseEntity<Void> responseEntity =
+                testRestTemplateService.invokeHttpPut(url, getServiceInstance(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+    }
+
+    private void invokeCustomerEndPointAndAssertResponse() throws Exception, IOException {
+        final ResponseEntity<Void> response =
+                testRestTemplateService.invokeHttpPut(getUrl(CUSTOMERS_URL), getCustomer(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/CloudRegionsControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/CloudRegionsControllerTest.java
new file mode 100755 (executable)
index 0000000..1b96759
--- /dev/null
@@ -0,0 +1,420 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.Constants.VSERVER;
+import static org.onap.so.aaisimulator.utils.TestConstants.CLOUD_OWNER_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.CLOUD_REGION_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.CUSTOMERS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_PASSWORD;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_SERVICE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_SYSTEM_INFO_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_SYSTEM_INFO_LIST_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_SYSTEM_TYPE;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_TYEP;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_USERNAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_VENDOR;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_SUBSCRIPTIONS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SYSTEM_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.TENANTS_TENANT;
+import static org.onap.so.aaisimulator.utils.TestConstants.TENANT_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.VNF_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.VSERVER_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.VSERVER_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.VSERVER_URL;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.CloudRegion;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrSystemInfoList;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.RelatedToProperty;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.aai.domain.yang.Tenant;
+import org.onap.aai.domain.yang.Vserver;
+import org.onap.so.aaisimulator.models.CloudRegionKey;
+import org.onap.so.aaisimulator.service.providers.CloudRegionCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.CustomerCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.GenericVnfCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.aaisimulator.utils.TestConstants;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class CloudRegionsControllerTest extends AbstractSpringBootTest {
+
+    private static final CloudRegionKey CLOUD_REGION_KEY = new CloudRegionKey(CLOUD_OWNER_NAME, CLOUD_REGION_NAME);
+
+    @Autowired
+    private CloudRegionCacheServiceProvider cloudRegionCacheServiceProvider;
+
+    @Autowired
+    private CustomerCacheServiceProvider customerCacheServiceProvider;
+
+    @Autowired
+    private GenericVnfCacheServiceProvider genericVnfCacheServiceProvider;
+
+    @After
+    public void after() {
+        cloudRegionCacheServiceProvider.clearAll();
+        customerCacheServiceProvider.clearAll();
+        genericVnfCacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_putCloudRegion_successfullyAddedToCache() throws Exception {
+        final String url = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+
+        invokeCloudRegionHttpPutEndPointAndAssertResponse(url);
+
+        final ResponseEntity<CloudRegion> response = testRestTemplateService.invokeHttpGet(url, CloudRegion.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final CloudRegion cloudRegion = response.getBody();
+        assertEquals(CLOUD_OWNER_NAME, cloudRegion.getCloudOwner());
+        assertEquals(CLOUD_REGION_NAME, cloudRegion.getCloudRegionId());
+
+        assertNotNull("ResourceVersion should not be null", cloudRegion.getResourceVersion());
+
+    }
+
+    @Test
+    public void test_getCloudRegionWithDepthValue_shouldReturnMatchedCloudRegion() throws Exception {
+        final String url = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+
+        invokeCloudRegionHttpPutEndPointAndAssertResponse(url);
+
+        final ResponseEntity<CloudRegion> response =
+                testRestTemplateService.invokeHttpGet(url + "?depth=2", CloudRegion.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final CloudRegion cloudRegion = response.getBody();
+        assertEquals(CLOUD_OWNER_NAME, cloudRegion.getCloudOwner());
+        assertEquals(CLOUD_REGION_NAME, cloudRegion.getCloudRegionId());
+
+        assertNotNull("ResourceVersion should not be null", cloudRegion.getResourceVersion());
+
+    }
+
+    @Test
+    public void test_putGenericVnfRelationShipToPlatform_successfullyAddedToCache() throws Exception {
+
+        final String url = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+
+        invokeCloudRegionHttpPutEndPointAndAssertResponse(url);
+
+        final String relationShipUrl = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME,
+                BI_DIRECTIONAL_RELATIONSHIP_LIST_URL);
+
+        final ResponseEntity<Relationship> responseEntity = testRestTemplateService.invokeHttpPut(relationShipUrl,
+                TestUtils.getGenericVnfRelationShip(), Relationship.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+
+        final Optional<CloudRegion> optional = cloudRegionCacheServiceProvider.getCloudRegion(CLOUD_REGION_KEY);
+        assertTrue(optional.isPresent());
+
+        final CloudRegion actual = optional.get();
+
+        assertNotNull(actual.getRelationshipList());
+        final List<Relationship> relationshipList = actual.getRelationshipList().getRelationship();
+        assertFalse("Relationship list should not be empty", relationshipList.isEmpty());
+        final Relationship relationship = relationshipList.get(0);
+
+        assertEquals(GENERIC_VNF_URL + VNF_ID, relationship.getRelatedLink());
+
+        assertFalse("RelationshipData list should not be empty", relationship.getRelationshipData().isEmpty());
+        assertFalse("RelatedToProperty list should not be empty", relationship.getRelatedToProperty().isEmpty());
+
+        final RelationshipData relationshipData = relationship.getRelationshipData().get(0);
+        assertEquals(Constants.GENERIC_VNF_VNF_ID, relationshipData.getRelationshipKey());
+        assertEquals(TestConstants.VNF_ID, relationshipData.getRelationshipValue());
+
+        final RelatedToProperty relatedToProperty = relationship.getRelatedToProperty().get(0);
+        assertEquals(Constants.GENERIC_VNF_VNF_NAME, relatedToProperty.getPropertyKey());
+        assertEquals(TestConstants.GENERIC_VNF_NAME, relatedToProperty.getPropertyValue());
+
+    }
+
+    @Test
+    public void test_putTenant_successfullyAddedToCache() throws Exception {
+        final String cloudRegionUrl = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+
+        invokeCloudRegionHttpPutEndPointAndAssertResponse(cloudRegionUrl);
+
+        final String tenantUrl = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME,
+                "/" + CLOUD_REGION_NAME + TENANTS_TENANT + TENANT_ID);
+        addTenantAndAssertResponse(tenantUrl);
+
+        final ResponseEntity<Tenant> response = testRestTemplateService.invokeHttpGet(tenantUrl, Tenant.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final Tenant tenant = response.getBody();
+        assertEquals(TENANT_ID, tenant.getTenantId());
+        assertEquals("admin", tenant.getTenantName());
+
+        assertNotNull("ResourceVersion should not be null", tenant.getResourceVersion());
+
+    }
+
+    @Test
+    public void test_putTenantRelationToGenericVnf_successfullyAddedToCache() throws Exception {
+
+        addCustomerServiceAndGenericVnf();
+
+        final String cloudRegionUrl = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+        invokeCloudRegionHttpPutEndPointAndAssertResponse(cloudRegionUrl);
+
+        final String tenantUrl = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME,
+                TENANTS_TENANT + TENANT_ID);
+        addTenantAndAssertResponse(tenantUrl);
+
+        final String tenantRelationShipUrl = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME,
+                "/" + CLOUD_REGION_NAME, TENANTS_TENANT + TENANT_ID, RELATIONSHIP_LIST_RELATIONSHIP_URL);
+
+        final ResponseEntity<Void> tenantRelationShipResponse = testRestTemplateService
+                .invokeHttpPut(tenantRelationShipUrl, TestUtils.getGenericVnfRelatedLink(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, tenantRelationShipResponse.getStatusCode());
+
+        final Optional<Tenant> optional = cloudRegionCacheServiceProvider.getTenant(CLOUD_REGION_KEY, TENANT_ID);
+
+        assertTrue(optional.isPresent());
+        final Tenant actualTenant = optional.get();
+        final RelationshipList relationshipList = actualTenant.getRelationshipList();
+        assertNotNull(relationshipList);
+        assertFalse(relationshipList.getRelationship().isEmpty());
+
+        final Relationship relationship = relationshipList.getRelationship().get(0);
+
+        assertEquals(Constants.BELONGS_TO, relationship.getRelationshipLabel());
+        assertFalse(relationship.getRelationshipData().isEmpty());
+        assertEquals(1, relationship.getRelationshipData().size());
+
+        final List<RelationshipData> relationshipDataList = relationship.getRelationshipData();
+
+        final RelationshipData relationshipData =
+                getRelationshipData(relationshipDataList, Constants.GENERIC_VNF_VNF_ID);
+        assertNotNull(relationshipData);
+        assertEquals(VNF_ID, relationshipData.getRelationshipValue());
+
+        final List<RelatedToProperty> relatedToPropertyList = relationship.getRelatedToProperty();
+
+        final RelatedToProperty property = getRelatedToProperty(relatedToPropertyList, Constants.GENERIC_VNF_VNF_NAME);
+        assertNotNull(property);
+        assertEquals(GENERIC_VNF_NAME, property.getPropertyValue());
+
+        final Optional<GenericVnf> genericVnfOptional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(genericVnfOptional.isPresent());
+        final GenericVnf actualGenericVnf = genericVnfOptional.get();
+        final RelationshipList relationshipListGenericVnf = actualGenericVnf.getRelationshipList();
+        assertNotNull(relationshipListGenericVnf);
+        assertFalse(relationshipListGenericVnf.getRelationship().isEmpty());
+
+        final Relationship relationshipGenericVnf = relationshipListGenericVnf.getRelationship().get(0);
+
+        assertEquals(Constants.BELONGS_TO, relationshipGenericVnf.getRelationshipLabel());
+        assertFalse(relationshipGenericVnf.getRelationshipData().isEmpty());
+        assertEquals(3, relationshipGenericVnf.getRelationshipData().size());
+
+    }
+
+    @Test
+    public void test_putEsrSystemInfo_successfullyAddedToCache() throws Exception {
+        final String url = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+
+        invokeCloudRegionHttpPutEndPointAndAssertResponse(url);
+
+        final String esrSystemInfoListUrl = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME,
+                "/" + CLOUD_REGION_NAME, ESR_SYSTEM_INFO_LIST_URL);
+
+        final String esrSystemInfoUrl = esrSystemInfoListUrl + "/esr-system-info/" + ESR_SYSTEM_INFO_ID;
+        final ResponseEntity<Void> esrSystemInfoResponse =
+                testRestTemplateService.invokeHttpPut(esrSystemInfoUrl, TestUtils.getEsrSystemInfo(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, esrSystemInfoResponse.getStatusCode());
+
+        final ResponseEntity<EsrSystemInfoList> response =
+                testRestTemplateService.invokeHttpGet(esrSystemInfoListUrl, EsrSystemInfoList.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+        final EsrSystemInfoList actualEsrSystemInfoList = response.getBody();
+
+        final List<EsrSystemInfo> esrSystemInfoList = actualEsrSystemInfoList.getEsrSystemInfo();
+        assertNotNull(esrSystemInfoList);
+        assertEquals(1, esrSystemInfoList.size());
+
+        final EsrSystemInfo esrSystemInfo = esrSystemInfoList.get(0);
+        assertEquals(ESR_SYSTEM_INFO_ID, esrSystemInfo.getEsrSystemInfoId());
+        assertEquals(SYSTEM_NAME, esrSystemInfo.getSystemName());
+        assertEquals(ESR_TYEP, esrSystemInfo.getType());
+        assertEquals(ESR_VENDOR, esrSystemInfo.getVendor());
+        assertEquals(ESR_SERVICE_URL, esrSystemInfo.getServiceUrl());
+        assertEquals(ESR_USERNAME, esrSystemInfo.getUserName());
+        assertEquals(ESR_PASSWORD, esrSystemInfo.getPassword());
+        assertEquals(ESR_SYSTEM_TYPE, esrSystemInfo.getSystemType());
+    }
+
+    @Test
+    public void test_putVServer_successfullyAddedToCache() throws Exception {
+        final String url = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+
+        invokeCloudRegionHttpPutEndPointAndAssertResponse(url);
+        addCustomerServiceAndGenericVnf();
+
+        final String tenantUrl = url + TENANTS_TENANT + TENANT_ID;
+        addTenantAndAssertResponse(tenantUrl);
+
+        final String vServerUrl = tenantUrl + VSERVER_URL + VSERVER_ID;
+
+        final ResponseEntity<Void> vServerResponse =
+                testRestTemplateService.invokeHttpPut(vServerUrl, TestUtils.getVserver(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, vServerResponse.getStatusCode());
+
+        final ResponseEntity<Vserver> response = testRestTemplateService.invokeHttpGet(vServerUrl, Vserver.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+        final Vserver actualVserver = response.getBody();
+        assertEquals(VSERVER_NAME, actualVserver.getVserverName());
+        assertEquals(VSERVER_ID, actualVserver.getVserverId());
+        assertEquals("active", actualVserver.getProvStatus());
+        assertNotNull(actualVserver.getRelationshipList());
+        assertFalse(actualVserver.getRelationshipList().getRelationship().isEmpty());
+
+        final Optional<GenericVnf> optional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(optional.isPresent());
+        final GenericVnf genericVnf = optional.get();
+        assertNotNull(genericVnf.getRelationshipList());
+        assertFalse(genericVnf.getRelationshipList().getRelationship().isEmpty());
+
+        final Relationship expectedRelationShip = genericVnf.getRelationshipList().getRelationship().get(0);
+        assertEquals(VSERVER, expectedRelationShip.getRelatedTo());
+        assertNotNull(expectedRelationShip.getRelationshipData());
+        assertEquals(4, expectedRelationShip.getRelationshipData().size());
+
+        final List<RelationshipData> relationshipDataList = expectedRelationShip.getRelationshipData();
+        final RelationshipData vServerrelationshipData =
+                getRelationshipData(relationshipDataList, Constants.VSERVER_VSERVER_ID);
+        assertNotNull(vServerrelationshipData);
+        assertEquals(VSERVER_ID, vServerrelationshipData.getRelationshipValue());
+
+        final RelationshipData cloudOwnerRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.CLOUD_REGION_CLOUD_OWNER);
+        assertNotNull(cloudOwnerRelationshipData);
+        assertEquals(CLOUD_OWNER_NAME, cloudOwnerRelationshipData.getRelationshipValue());
+
+        final RelationshipData cloudRegionIdRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.CLOUD_REGION_CLOUD_REGION_ID);
+        assertNotNull(cloudRegionIdRelationshipData);
+        assertEquals(CLOUD_REGION_NAME, cloudRegionIdRelationshipData.getRelationshipValue());
+
+        final RelationshipData tenantRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.TENANT_TENANT_ID);
+        assertNotNull(tenantRelationshipData);
+        assertEquals(TENANT_ID, tenantRelationshipData.getRelationshipValue());
+
+    }
+
+    @Test
+    public void test_deleteVServer_successfullyRemoveFromCache() throws Exception {
+        final String url = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+
+        invokeCloudRegionHttpPutEndPointAndAssertResponse(url);
+        addCustomerServiceAndGenericVnf();
+
+        final String tenantUrl = url + TENANTS_TENANT + TENANT_ID;
+        addTenantAndAssertResponse(tenantUrl);
+
+        final String vServerAddUrl = tenantUrl + VSERVER_URL + VSERVER_ID;
+
+        final ResponseEntity<Void> vServerAddResponse =
+                testRestTemplateService.invokeHttpPut(vServerAddUrl, TestUtils.getVserver(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, vServerAddResponse.getStatusCode());
+
+        final Optional<Vserver> optional =
+                cloudRegionCacheServiceProvider.getVserver(CLOUD_REGION_KEY, TENANT_ID, VSERVER_ID);
+        assertTrue(optional.isPresent());
+        final Vserver vserver = optional.get();
+
+        final String vServerRemoveUrl = vServerAddUrl + "?resource-version=" + vserver.getResourceVersion();
+
+        final ResponseEntity<Void> responseEntity =
+                testRestTemplateService.invokeHttpDelete(vServerRemoveUrl, Void.class);
+        assertEquals(HttpStatus.NO_CONTENT, responseEntity.getStatusCode());
+        assertFalse(cloudRegionCacheServiceProvider.getVserver(CLOUD_REGION_KEY, TENANT_ID, VSERVER_ID).isPresent());
+
+
+    }
+
+    private void addTenantAndAssertResponse(final String tenantUrl) throws IOException {
+        final ResponseEntity<Void> responseEntity =
+                testRestTemplateService.invokeHttpPut(tenantUrl, TestUtils.getTenant(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+    }
+
+    private void addCustomerServiceAndGenericVnf() throws Exception, IOException {
+        final ResponseEntity<Void> customerResponse =
+                testRestTemplateService.invokeHttpPut(getUrl(CUSTOMERS_URL), TestUtils.getCustomer(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, customerResponse.getStatusCode());
+
+        final String serviceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+        final ResponseEntity<Void> serviceInstanceResponse =
+                testRestTemplateService.invokeHttpPut(serviceInstanceUrl, TestUtils.getServiceInstance(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, serviceInstanceResponse.getStatusCode());
+
+        final String genericVnfUrl = getUrl(GENERIC_VNF_URL, VNF_ID);
+        final ResponseEntity<Void> genericVnfResponse =
+                testRestTemplateService.invokeHttpPut(genericVnfUrl, TestUtils.getGenericVnf(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, genericVnfResponse.getStatusCode());
+
+    }
+
+    private void invokeCloudRegionHttpPutEndPointAndAssertResponse(final String url) throws IOException {
+        final ResponseEntity<Void> responseEntity =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getCloudRegion(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/ExternalSystemEsrControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/ExternalSystemEsrControllerTest.java
new file mode 100755 (executable)
index 0000000..2fd5f7b
--- /dev/null
@@ -0,0 +1,233 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.CUSTOMERS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_PASSWORD;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_SERVICE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_SYSTEM_INFO_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_SYSTEM_INFO_LIST_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_SYSTEM_TYPE;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_TYEP;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_USERNAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_VENDOR;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_VIM_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_VNFM_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.ESR_VNFM_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_SUBSCRIPTIONS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SYSTEM_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.VNF_ID;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.EsrSystemInfo;
+import org.onap.aai.domain.yang.EsrSystemInfoList;
+import org.onap.aai.domain.yang.EsrVnfm;
+import org.onap.aai.domain.yang.EsrVnfmList;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.so.aaisimulator.service.providers.ExternalSystemCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.GenericVnfCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.aaisimulator.utils.TestConstants;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class ExternalSystemEsrControllerTest extends AbstractSpringBootTest {
+
+    @Autowired
+    private ExternalSystemCacheServiceProvider externalSystemCacheServiceProvider;
+
+
+    @Autowired
+    private GenericVnfCacheServiceProvider genericVnfCacheServiceProvider;
+
+    @After
+    public void after() {
+        externalSystemCacheServiceProvider.clearAll();
+        genericVnfCacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_putEsrVnfm_successfullyAddedToCache() throws Exception {
+        final String esrVnfmUrl = getUrl(ESR_VNFM_URL, ESR_VNFM_ID);
+        addEsrVnfmAndAssertResponse(esrVnfmUrl);
+
+        final ResponseEntity<EsrVnfm> response = testRestTemplateService.invokeHttpGet(esrVnfmUrl, EsrVnfm.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final EsrVnfm actualEsrVnfm = response.getBody();
+        assertEquals(ESR_VNFM_ID, actualEsrVnfm.getVnfmId());
+        assertEquals(ESR_VIM_ID, actualEsrVnfm.getVimId());
+
+    }
+
+    @Test
+    public void test_getEsrVnfmList_getAllEsrVnfmsFromCache() throws Exception {
+        final String esrVnfmUrl = getUrl(ESR_VNFM_URL, ESR_VNFM_ID);
+        addEsrVnfmAndAssertResponse(esrVnfmUrl);
+
+        final String esrVnfmListUrl = getUrl(TestConstants.EXTERNAL_SYSTEM_ESR_VNFM_LIST_URL);
+        final ResponseEntity<EsrVnfmList> response =
+                testRestTemplateService.invokeHttpGet(esrVnfmListUrl, EsrVnfmList.class);
+
+        assertTrue(response.hasBody());
+
+        final EsrVnfmList actualEsrVnfmList = response.getBody();
+
+        final List<EsrVnfm> esrVnfmList = actualEsrVnfmList.getEsrVnfm();
+        assertNotNull(esrVnfmList);
+        assertEquals(1, esrVnfmList.size());
+        final EsrVnfm actualEsrVnfm = esrVnfmList.get(0);
+        assertEquals(ESR_VNFM_ID, actualEsrVnfm.getVnfmId());
+        assertEquals(ESR_VIM_ID, actualEsrVnfm.getVimId());
+
+    }
+
+    @Test
+    public void test_putEsrSystemInfo_successfullyAddedToCache() throws Exception {
+        final String esrVnfmUrl = getUrl(ESR_VNFM_URL, ESR_VNFM_ID);
+        addEsrVnfmAndAssertResponse(esrVnfmUrl);
+        final String esrSystemInfoListUrl = getUrl(ESR_VNFM_URL, ESR_VNFM_ID, ESR_SYSTEM_INFO_LIST_URL);
+
+        final String esrSystemInfoUrl = esrSystemInfoListUrl + "/esr-system-info/" + ESR_SYSTEM_INFO_ID;
+        final ResponseEntity<Void> esrSystemInfoResponse =
+                testRestTemplateService.invokeHttpPut(esrSystemInfoUrl, TestUtils.getEsrSystemInfo(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, esrSystemInfoResponse.getStatusCode());
+
+        final ResponseEntity<EsrSystemInfoList> response =
+                testRestTemplateService.invokeHttpGet(esrSystemInfoListUrl, EsrSystemInfoList.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+        final EsrSystemInfoList actualEsrSystemInfoList = response.getBody();
+
+        final List<EsrSystemInfo> esrSystemInfoList = actualEsrSystemInfoList.getEsrSystemInfo();
+        assertNotNull(esrSystemInfoList);
+        assertEquals(1, esrSystemInfoList.size());
+
+        final EsrSystemInfo esrSystemInfo = esrSystemInfoList.get(0);
+        assertEquals(ESR_SYSTEM_INFO_ID, esrSystemInfo.getEsrSystemInfoId());
+        assertEquals(SYSTEM_NAME, esrSystemInfo.getSystemName());
+        assertEquals(ESR_TYEP, esrSystemInfo.getType());
+        assertEquals(ESR_VENDOR, esrSystemInfo.getVendor());
+        assertEquals(ESR_SERVICE_URL, esrSystemInfo.getServiceUrl());
+        assertEquals(ESR_USERNAME, esrSystemInfo.getUserName());
+        assertEquals(ESR_PASSWORD, esrSystemInfo.getPassword());
+        assertEquals(ESR_SYSTEM_TYPE, esrSystemInfo.getSystemType());
+
+
+    }
+
+    @Test
+    public void test_putEsrRelationToGenericVnfm_successfullyAddedToCache() throws Exception {
+        final String esrVnfmUrl = getUrl(ESR_VNFM_URL, ESR_VNFM_ID);
+
+        addEsrVnfmAndAssertResponse(esrVnfmUrl);
+        addCustomerServiceAndGenericVnf();
+
+        final String relationShipUrl = esrVnfmUrl + RELATIONSHIP_LIST_RELATIONSHIP_URL;
+
+        final ResponseEntity<Void> response = testRestTemplateService.invokeHttpPut(relationShipUrl,
+                TestUtils.getGenericVnfRelatedLink(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+
+        final Optional<EsrVnfm> optional = externalSystemCacheServiceProvider.getEsrVnfm(ESR_VNFM_ID);
+        assertTrue(optional.isPresent());
+
+        final EsrVnfm actualEsrVnfm = optional.get();
+        final RelationshipList relationshipList = actualEsrVnfm.getRelationshipList();
+        assertNotNull(relationshipList);
+        assertFalse(relationshipList.getRelationship().isEmpty());
+
+        final Relationship relationship = relationshipList.getRelationship().get(0);
+
+        assertEquals(Constants.DEPENDS_ON, relationship.getRelationshipLabel());
+        assertFalse(relationship.getRelationshipData().isEmpty());
+        assertEquals(1, relationship.getRelationshipData().size());
+
+        final RelationshipData relationshipData =
+                getRelationshipData(relationship.getRelationshipData(), Constants.GENERIC_VNF_VNF_ID);
+        assertNotNull(relationshipData);
+        assertEquals(VNF_ID, relationshipData.getRelationshipValue());
+
+        final Optional<GenericVnf> genericVnfOptional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(genericVnfOptional.isPresent());
+        final GenericVnf actualGenericVnf = genericVnfOptional.get();
+        final RelationshipList relationshipListGenericVnf = actualGenericVnf.getRelationshipList();
+        assertNotNull(relationshipListGenericVnf);
+        assertFalse(relationshipListGenericVnf.getRelationship().isEmpty());
+
+        final Relationship relationshipGenericVnf = relationshipListGenericVnf.getRelationship().get(0);
+
+        assertEquals(Constants.DEPENDS_ON, relationshipGenericVnf.getRelationshipLabel());
+        assertFalse(relationshipGenericVnf.getRelationshipData().isEmpty());
+        assertEquals(1, relationshipGenericVnf.getRelationshipData().size());
+
+        final RelationshipData esrRelationshipData =
+                getRelationshipData(relationshipGenericVnf.getRelationshipData(), Constants.ESR_VNFM_VNFM_ID);
+        assertNotNull(esrRelationshipData);
+        assertEquals(ESR_VNFM_ID, esrRelationshipData.getRelationshipValue());
+
+
+    }
+
+    private void addEsrVnfmAndAssertResponse(final String esrVnfmUrl) throws IOException {
+        final ResponseEntity<Void> esrVnfmResponse =
+                testRestTemplateService.invokeHttpPut(esrVnfmUrl, TestUtils.getEsrVnfm(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, esrVnfmResponse.getStatusCode());
+    }
+
+    private void addCustomerServiceAndGenericVnf() throws Exception, IOException {
+        final ResponseEntity<Void> customerResponse =
+                testRestTemplateService.invokeHttpPut(getUrl(CUSTOMERS_URL), TestUtils.getCustomer(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, customerResponse.getStatusCode());
+
+        final String serviceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+        final ResponseEntity<Void> serviceInstanceResponse =
+                testRestTemplateService.invokeHttpPut(serviceInstanceUrl, TestUtils.getServiceInstance(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, serviceInstanceResponse.getStatusCode());
+
+        final String genericVnfUrl = getUrl(GENERIC_VNF_URL, VNF_ID);
+        final ResponseEntity<Void> genericVnfResponse =
+                testRestTemplateService.invokeHttpPut(genericVnfUrl, TestUtils.getGenericVnf(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, genericVnfResponse.getStatusCode());
+
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/GenericVnfsControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/GenericVnfsControllerTest.java
new file mode 100755 (executable)
index 0000000..8b6ec8c
--- /dev/null
@@ -0,0 +1,430 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.Constants.X_HTTP_METHOD_OVERRIDE;
+import static org.onap.so.aaisimulator.utils.TestConstants.CLOUD_OWNER_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.CLOUD_REGION_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.CUSTOMERS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GLOBAL_CUSTOMER_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.LINE_OF_BUSINESS_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.PLATFORM_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_SUBSCRIPTIONS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_TYPE;
+import static org.onap.so.aaisimulator.utils.TestConstants.VNF_ID;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.GenericVnfs;
+import org.onap.aai.domain.yang.RelatedToProperty;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.RelationshipList;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.so.aaisimulator.service.providers.CustomerCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.GenericVnfCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.LinesOfBusinessCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.PlatformCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.aaisimulator.utils.TestConstants;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class GenericVnfsControllerTest extends AbstractSpringBootTest {
+
+    @Autowired
+    private CustomerCacheServiceProvider customerCacheServiceProvider;
+
+    @Autowired
+    private GenericVnfCacheServiceProvider genericVnfCacheServiceProvider;
+
+    @Autowired
+    private LinesOfBusinessCacheServiceProvider linesOfBusinessCacheServiceProvider;
+
+    @Autowired
+    private PlatformCacheServiceProvider platformVnfCacheServiceProvider;
+
+    @After
+    public void after() {
+        customerCacheServiceProvider.clearAll();
+        genericVnfCacheServiceProvider.clearAll();
+        platformVnfCacheServiceProvider.clearAll();
+        linesOfBusinessCacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_putGenericVnf_successfullyAddedToCache() throws Exception {
+
+        final String genericVnfUrl = getUrl(GENERIC_VNF_URL, VNF_ID);
+        final ResponseEntity<Void> genericVnfResponse =
+                testRestTemplateService.invokeHttpPut(genericVnfUrl, TestUtils.getGenericVnf(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, genericVnfResponse.getStatusCode());
+
+        final ResponseEntity<GenericVnf> response =
+                testRestTemplateService.invokeHttpGet(genericVnfUrl, GenericVnf.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final GenericVnf actualGenericVnf = response.getBody();
+        assertEquals(GENERIC_VNF_NAME, actualGenericVnf.getVnfName());
+        assertEquals(VNF_ID, actualGenericVnf.getVnfId());
+
+    }
+
+    @Test
+    public void test_putGenericVnfRelation_successfullyAddedToCache() throws Exception {
+
+        addCustomerServiceAndGenericVnf();
+
+        final String genericVnfRelationShipUrl = getUrl(GENERIC_VNF_URL, VNF_ID, RELATIONSHIP_LIST_RELATIONSHIP_URL);
+        final ResponseEntity<Void> genericVnfRelationShipResponse = testRestTemplateService
+                .invokeHttpPut(genericVnfRelationShipUrl, TestUtils.getRelationShip(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, genericVnfRelationShipResponse.getStatusCode());
+
+
+        final Optional<ServiceInstance> optional =
+                customerCacheServiceProvider.getServiceInstance(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, SERVICE_INSTANCE_ID);
+
+        assertTrue(optional.isPresent());
+
+        final ServiceInstance actualServiceInstance = optional.get();
+        final RelationshipList actualRelationshipList = actualServiceInstance.getRelationshipList();
+        assertNotNull(actualRelationshipList);
+        assertFalse(actualRelationshipList.getRelationship().isEmpty());
+        final Relationship actualRelationShip = actualRelationshipList.getRelationship().get(0);
+
+        assertEquals(Constants.COMPOSED_OF, actualRelationShip.getRelationshipLabel());
+        assertEquals(GENERIC_VNF_URL + VNF_ID, actualRelationShip.getRelatedLink());
+
+
+        assertFalse(actualRelationShip.getRelatedToProperty().isEmpty());
+        assertFalse(actualRelationShip.getRelationshipData().isEmpty());
+        final RelatedToProperty actualRelatedToProperty = actualRelationShip.getRelatedToProperty().get(0);
+        final RelationshipData actualRelationshipData = actualRelationShip.getRelationshipData().get(0);
+
+        assertEquals(Constants.GENERIC_VNF_VNF_NAME, actualRelatedToProperty.getPropertyKey());
+        assertEquals(GENERIC_VNF_NAME, actualRelatedToProperty.getPropertyValue());
+        assertEquals(Constants.GENERIC_VNF_VNF_ID, actualRelationshipData.getRelationshipKey());
+        assertEquals(VNF_ID, actualRelationshipData.getRelationshipValue());
+
+        final Optional<GenericVnf> genericVnfOptional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(genericVnfOptional.isPresent());
+        final GenericVnf actualGenericVnf = genericVnfOptional.get();
+        final RelationshipList relationshipList = actualGenericVnf.getRelationshipList();
+        assertNotNull(relationshipList);
+        assertFalse(relationshipList.getRelationship().isEmpty());
+
+        final Relationship relationship = relationshipList.getRelationship().get(0);
+        assertFalse(relationship.getRelatedToProperty().isEmpty());
+        assertEquals(3, relationship.getRelationshipData().size());
+        assertEquals(CUSTOMERS_URL + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCE_URL, relationship.getRelatedLink());
+
+
+        final List<RelatedToProperty> relatedToProperty = relationship.getRelatedToProperty();
+        final RelatedToProperty firstRelatedToProperty = relatedToProperty.get(0);
+        assertEquals(Constants.SERVICE_INSTANCE_SERVICE_INSTANCE_NAME, firstRelatedToProperty.getPropertyKey());
+        assertEquals(SERVICE_NAME, firstRelatedToProperty.getPropertyValue());
+
+        final List<RelationshipData> relationshipData = relationship.getRelationshipData();
+
+        final RelationshipData globalRelationshipData =
+                getRelationshipData(relationshipData, Constants.CUSTOMER_GLOBAL_CUSTOMER_ID);
+        assertNotNull(globalRelationshipData);
+        assertEquals(GLOBAL_CUSTOMER_ID, globalRelationshipData.getRelationshipValue());
+
+        final RelationshipData serviceSubscriptionRelationshipData =
+                getRelationshipData(relationshipData, Constants.SERVICE_SUBSCRIPTION_SERVICE_TYPE);
+        assertNotNull(serviceSubscriptionRelationshipData);
+        assertEquals(SERVICE_TYPE, serviceSubscriptionRelationshipData.getRelationshipValue());
+
+        final RelationshipData serviceInstanceRelationshipData =
+                getRelationshipData(relationshipData, Constants.SERVICE_INSTANCE_SERVICE_INSTANCE_ID);
+        assertNotNull(serviceInstanceRelationshipData);
+        assertEquals(SERVICE_INSTANCE_ID, serviceInstanceRelationshipData.getRelationshipValue());
+
+    }
+
+    @Test
+    public void test_putGenericVnfRelationToPlatform_successfullyAddedToCache() throws Exception {
+        addCustomerServiceAndGenericVnf();
+
+        final String platformUrl = getUrl(TestConstants.PLATFORMS_URL, PLATFORM_NAME);
+        final ResponseEntity<Void> platformResponse =
+                testRestTemplateService.invokeHttpPut(platformUrl, TestUtils.getPlatform(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, platformResponse.getStatusCode());
+
+        final String genericVnfRelationShipUrl = getUrl(GENERIC_VNF_URL, VNF_ID, RELATIONSHIP_LIST_RELATIONSHIP_URL);
+        final ResponseEntity<Void> genericVnfRelationShipResponse = testRestTemplateService
+                .invokeHttpPut(genericVnfRelationShipUrl, TestUtils.getPlatformRelatedLink(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, genericVnfRelationShipResponse.getStatusCode());
+
+        final Optional<GenericVnf> genericVnfOptional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(genericVnfOptional.isPresent());
+        final GenericVnf actualGenericVnf = genericVnfOptional.get();
+        final RelationshipList relationshipList = actualGenericVnf.getRelationshipList();
+        assertNotNull(relationshipList);
+        assertFalse(relationshipList.getRelationship().isEmpty());
+
+        final Relationship relationship = relationshipList.getRelationship().get(0);
+
+        assertEquals(Constants.USES, relationship.getRelationshipLabel());
+        assertFalse(relationship.getRelationshipData().isEmpty());
+        assertEquals(1, relationship.getRelationshipData().size());
+        assertEquals(TestConstants.PLATFORMS_URL + PLATFORM_NAME, relationship.getRelatedLink());
+
+
+        final List<RelationshipData> relationshipData = relationship.getRelationshipData();
+
+        final RelationshipData platformRelationshipData =
+                getRelationshipData(relationshipData, Constants.PLATFORM_PLATFORM_NAME);
+        assertNotNull(platformRelationshipData);
+        assertEquals(PLATFORM_NAME, platformRelationshipData.getRelationshipValue());
+
+    }
+
+    @Test
+    public void test_putGenericVnfRelationToLineOfBusiness_successfullyAddedToCache() throws Exception {
+        addCustomerServiceAndGenericVnf();
+
+        final String url = getUrl(TestConstants.LINES_OF_BUSINESS_URL, LINE_OF_BUSINESS_NAME);
+        final ResponseEntity<Void> responseEntity =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getLineOfBusiness(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+
+        final String genericVnfRelationShipUrl = getUrl(GENERIC_VNF_URL, VNF_ID, RELATIONSHIP_LIST_RELATIONSHIP_URL);
+        final ResponseEntity<Void> genericVnfRelationShipResponse = testRestTemplateService
+                .invokeHttpPut(genericVnfRelationShipUrl, TestUtils.getLineOfBusinessRelatedLink(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, genericVnfRelationShipResponse.getStatusCode());
+
+        final Optional<GenericVnf> genericVnfOptional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(genericVnfOptional.isPresent());
+        final GenericVnf actualGenericVnf = genericVnfOptional.get();
+        final RelationshipList relationshipList = actualGenericVnf.getRelationshipList();
+        assertNotNull(relationshipList);
+        assertFalse(relationshipList.getRelationship().isEmpty());
+
+        final Relationship relationship = relationshipList.getRelationship().get(0);
+
+        assertEquals(Constants.USES, relationship.getRelationshipLabel());
+        assertEquals(TestConstants.LINES_OF_BUSINESS_URL + LINE_OF_BUSINESS_NAME, relationship.getRelatedLink());
+
+        assertFalse(relationship.getRelationshipData().isEmpty());
+        assertEquals(1, relationship.getRelationshipData().size());
+
+        final List<RelationshipData> relationshipData = relationship.getRelationshipData();
+
+        final RelationshipData lineOfBusinessRelationshipData =
+                getRelationshipData(relationshipData, Constants.LINE_OF_BUSINESS_LINE_OF_BUSINESS_NAME);
+        assertNotNull(lineOfBusinessRelationshipData);
+        assertEquals(LINE_OF_BUSINESS_NAME, lineOfBusinessRelationshipData.getRelationshipValue());
+
+    }
+
+    @Test
+    public void test_putGenericVnfRelationToCloudRegion_successfullyAddedToCache() throws Exception {
+        addCustomerServiceAndGenericVnf();
+
+        final String url = getUrl(TestConstants.CLOUD_REGIONS, CLOUD_OWNER_NAME, "/" + CLOUD_REGION_NAME);
+
+        final ResponseEntity<Void> responseEntity =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getCloudRegion(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+
+        final String genericVnfRelationShipUrl = getUrl(GENERIC_VNF_URL, VNF_ID, RELATIONSHIP_LIST_RELATIONSHIP_URL);
+        final ResponseEntity<Void> genericVnfRelationShipResponse = testRestTemplateService
+                .invokeHttpPut(genericVnfRelationShipUrl, TestUtils.getCloudRegionRelatedLink(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, genericVnfRelationShipResponse.getStatusCode());
+
+        final Optional<GenericVnf> genericVnfOptional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(genericVnfOptional.isPresent());
+        final GenericVnf actualGenericVnf = genericVnfOptional.get();
+        final RelationshipList relationshipList = actualGenericVnf.getRelationshipList();
+        assertNotNull(relationshipList);
+        assertFalse(relationshipList.getRelationship().isEmpty());
+
+        final Relationship relationship = relationshipList.getRelationship().get(0);
+
+        assertEquals(Constants.LOCATED_IN, relationship.getRelationshipLabel());
+        assertEquals(TestConstants.CLOUD_REGIONS + CLOUD_OWNER_NAME + "/" + CLOUD_REGION_NAME,
+                relationship.getRelatedLink());
+
+        assertFalse(relationship.getRelationshipData().isEmpty());
+        assertEquals(2, relationship.getRelationshipData().size());
+
+        final List<RelationshipData> relationshipDataList = relationship.getRelationshipData();
+
+        final RelationshipData cloudOwnerRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.CLOUD_REGION_CLOUD_OWNER);
+        assertNotNull(cloudOwnerRelationshipData);
+        assertEquals(CLOUD_OWNER_NAME, cloudOwnerRelationshipData.getRelationshipValue());
+
+        final RelationshipData cloudRegionIdRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.CLOUD_REGION_CLOUD_REGION_ID);
+        assertNotNull(cloudRegionIdRelationshipData);
+        assertEquals(CLOUD_REGION_NAME, cloudRegionIdRelationshipData.getRelationshipValue());
+
+        final List<RelatedToProperty> relatedToPropertyList = relationship.getRelatedToProperty();
+
+        final RelatedToProperty cloudRegionOwnerDefinedTypeProperty =
+                getRelatedToProperty(relatedToPropertyList, Constants.CLOUD_REGION_OWNER_DEFINED_TYPE);
+        assertNotNull(cloudRegionOwnerDefinedTypeProperty);
+        assertEquals("OwnerType", cloudRegionOwnerDefinedTypeProperty.getPropertyValue());
+
+    }
+
+    @Test
+    public void test_putBiDirectionalRelationShip_successfullyAddedToCache() throws Exception {
+        addCustomerServiceAndGenericVnf();
+
+        final String relationShipUrl = getUrl(GENERIC_VNF_URL, VNF_ID, BI_DIRECTIONAL_RELATIONSHIP_LIST_URL);
+
+        final ResponseEntity<Relationship> responseEntity = testRestTemplateService.invokeHttpPut(relationShipUrl,
+                TestUtils.getTenantRelationShip(), Relationship.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+
+        final Optional<GenericVnf> optional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(optional.isPresent());
+
+        final GenericVnf actual = optional.get();
+
+        assertNotNull(actual.getRelationshipList());
+        final List<Relationship> relationshipList = actual.getRelationshipList().getRelationship();
+        assertFalse("Relationship list should not be empty", relationshipList.isEmpty());
+        final Relationship relationship = relationshipList.get(0);
+
+        assertFalse("RelationshipData list should not be empty", relationship.getRelationshipData().isEmpty());
+        assertFalse("RelatedToProperty list should not be empty", relationship.getRelatedToProperty().isEmpty());
+    }
+
+    @Test
+    public void test_patchGenericVnf_usingVnfId_OrchStatusChangedInCache() throws Exception {
+        addCustomerServiceAndGenericVnf();
+
+        final HttpHeaders httpHeaders = testRestTemplateService.getHttpHeaders();
+        httpHeaders.add(X_HTTP_METHOD_OVERRIDE, HttpMethod.PATCH.toString());
+        httpHeaders.remove(HttpHeaders.CONTENT_TYPE);
+        httpHeaders.add(HttpHeaders.CONTENT_TYPE, Constants.APPLICATION_MERGE_PATCH_JSON);
+
+        final String genericVnfUrl = getUrl(GENERIC_VNF_URL, VNF_ID);
+        final ResponseEntity<Void> orchStatuUpdateServiceInstanceResponse = testRestTemplateService
+                .invokeHttpPost(httpHeaders, genericVnfUrl, TestUtils.getGenericVnfOrchStatuUpdate(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, orchStatuUpdateServiceInstanceResponse.getStatusCode());
+
+        final ResponseEntity<GenericVnf> response =
+                testRestTemplateService.invokeHttpGet(genericVnfUrl, GenericVnf.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final GenericVnf actualGenericVnf = response.getBody();
+        assertEquals(GENERIC_VNF_NAME, actualGenericVnf.getVnfName());
+        assertEquals(VNF_ID, actualGenericVnf.getVnfId());
+        assertEquals("Assigned", actualGenericVnf.getOrchestrationStatus());
+
+    }
+
+    @Test
+    public void test_getGenericVnfs_usingSelfLink_getAllGenericVnfsInCache() throws Exception {
+
+        addCustomerServiceAndGenericVnf();
+
+        final String selfLink = "http://localhost:9921/generic-vnf/" + VNF_ID;
+        final String url = getUrl(TestConstants.GENERIC_VNFS_URL_1) + "?selflink=" + selfLink;
+        final ResponseEntity<GenericVnfs> response = testRestTemplateService.invokeHttpGet(url, GenericVnfs.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final GenericVnfs actualGenericVnfs = response.getBody();
+        final List<GenericVnf> genericVnfList = actualGenericVnfs.getGenericVnf();
+        assertNotNull(genericVnfList);
+        assertEquals(1, genericVnfList.size());
+        final GenericVnf actualGenericVnf = genericVnfList.get(0);
+        assertEquals(selfLink, actualGenericVnf.getSelflink());
+        assertEquals(GENERIC_VNF_NAME, actualGenericVnf.getVnfName());
+        assertEquals(VNF_ID, actualGenericVnf.getVnfId());
+    }
+
+    @Test
+    public void test_deleteGenericVnf_usingVnfIdAndResourceVersion_removedFromCache() throws Exception {
+
+        addCustomerServiceAndGenericVnf();
+
+        final Optional<GenericVnf> genericVnfOptional = genericVnfCacheServiceProvider.getGenericVnf(VNF_ID);
+        assertTrue(genericVnfOptional.isPresent());
+        final GenericVnf genericVnf = genericVnfOptional.get();
+
+        final String genericVnfDeleteUrl =
+                getUrl(GENERIC_VNF_URL, genericVnf.getVnfId()) + "?resource-version=" + genericVnf.getResourceVersion();
+
+        final ResponseEntity<Void> responseEntity =
+                testRestTemplateService.invokeHttpDelete(genericVnfDeleteUrl, Void.class);
+        assertEquals(HttpStatus.NO_CONTENT, responseEntity.getStatusCode());
+        assertFalse(genericVnfCacheServiceProvider.getGenericVnf(VNF_ID).isPresent());
+
+    }
+
+    private void addCustomerServiceAndGenericVnf() throws Exception, IOException {
+        final ResponseEntity<Void> customerResponse =
+                testRestTemplateService.invokeHttpPut(getUrl(CUSTOMERS_URL), TestUtils.getCustomer(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, customerResponse.getStatusCode());
+
+        final String serviceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+        final ResponseEntity<Void> serviceInstanceResponse =
+                testRestTemplateService.invokeHttpPut(serviceInstanceUrl, TestUtils.getServiceInstance(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, serviceInstanceResponse.getStatusCode());
+
+        final String genericVnfUrl = getUrl(GENERIC_VNF_URL, VNF_ID);
+        final ResponseEntity<Void> genericVnfResponse =
+                testRestTemplateService.invokeHttpPut(genericVnfUrl, TestUtils.getGenericVnf(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, genericVnfResponse.getStatusCode());
+
+    }
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/LinesOfBusinessControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/LinesOfBusinessControllerTest.java
new file mode 100755 (executable)
index 0000000..30b3d27
--- /dev/null
@@ -0,0 +1,143 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.LINE_OF_BUSINESS_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.VNF_ID;
+import java.util.List;
+import java.util.Optional;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.LineOfBusiness;
+import org.onap.aai.domain.yang.RelatedToProperty;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.LinesOfBusinessCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.aaisimulator.utils.TestConstants;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class LinesOfBusinessControllerTest extends AbstractSpringBootTest {
+
+    @Autowired
+    private LinesOfBusinessCacheServiceProvider linesOfBusinessCacheServiceProvider;
+
+    @After
+    public void after() {
+        linesOfBusinessCacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_putLineOfBusiness_successfullyAddedToCache() throws Exception {
+
+        final String url = getUrl(TestConstants.LINES_OF_BUSINESS_URL, LINE_OF_BUSINESS_NAME);
+        final ResponseEntity<Void> lineOfBusinessResponse =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getLineOfBusiness(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, lineOfBusinessResponse.getStatusCode());
+
+        final ResponseEntity<LineOfBusiness> response =
+                testRestTemplateService.invokeHttpGet(url, LineOfBusiness.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final LineOfBusiness actualLineOfBusiness = response.getBody();
+        assertEquals(LINE_OF_BUSINESS_NAME, actualLineOfBusiness.getLineOfBusinessName());
+        assertNotNull("resource version should not be null", actualLineOfBusiness.getResourceVersion());
+
+    }
+
+    @Test
+    public void test_getLineOfBusinessWithFormatCount() throws Exception {
+
+        final String url = getUrl(TestConstants.LINES_OF_BUSINESS_URL, LINE_OF_BUSINESS_NAME);
+        final ResponseEntity<Void> lineOfBusinessResponse =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getLineOfBusiness(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, lineOfBusinessResponse.getStatusCode());
+
+        final ResponseEntity<Results> response = testRestTemplateService
+                .invokeHttpGet(url + "?resultIndex=0&resultSize=1&format=" + Format.COUNT.getValue(), Results.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final Results result = response.getBody();
+        assertNotNull(result.getValues());
+        assertFalse(result.getValues().isEmpty());
+        assertEquals(1, result.getValues().get(0).get(Constants.LINE_OF_BUSINESS));
+    }
+
+
+    @Test
+    public void test_putGenericVnfRelationShipToPlatform_successfullyAddedToCache() throws Exception {
+
+        final String url = getUrl(TestConstants.LINES_OF_BUSINESS_URL, LINE_OF_BUSINESS_NAME);
+        final ResponseEntity<Void> response =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getLineOfBusiness(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+
+        final String relationShipUrl = getUrl(TestConstants.LINES_OF_BUSINESS_URL, LINE_OF_BUSINESS_NAME,
+                BI_DIRECTIONAL_RELATIONSHIP_LIST_URL);
+
+        final ResponseEntity<Relationship> responseEntity = testRestTemplateService.invokeHttpPut(relationShipUrl,
+                TestUtils.getGenericVnfRelationShip(), Relationship.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+
+        final Optional<LineOfBusiness> optional =
+                linesOfBusinessCacheServiceProvider.getLineOfBusiness(LINE_OF_BUSINESS_NAME);
+        assertTrue(optional.isPresent());
+
+        final LineOfBusiness actual = optional.get();
+
+        assertNotNull(actual.getRelationshipList());
+        final List<Relationship> relationshipList = actual.getRelationshipList().getRelationship();
+        assertFalse("Relationship list should not be empty", relationshipList.isEmpty());
+        final Relationship relationship = relationshipList.get(0);
+
+        assertEquals(GENERIC_VNF_URL + VNF_ID, relationship.getRelatedLink());
+        assertFalse("RelationshipData list should not be empty", relationship.getRelationshipData().isEmpty());
+        assertFalse("RelatedToProperty list should not be empty", relationship.getRelatedToProperty().isEmpty());
+
+        final RelationshipData relationshipData = relationship.getRelationshipData().get(0);
+        assertEquals(Constants.GENERIC_VNF_VNF_ID, relationshipData.getRelationshipKey());
+        assertEquals(TestConstants.VNF_ID, relationshipData.getRelationshipValue());
+
+        final RelatedToProperty relatedToProperty = relationship.getRelatedToProperty().get(0);
+        assertEquals(Constants.GENERIC_VNF_VNF_NAME, relatedToProperty.getPropertyKey());
+        assertEquals(TestConstants.GENERIC_VNF_NAME, relatedToProperty.getPropertyValue());
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/NodesControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/NodesControllerTest.java
new file mode 100755 (executable)
index 0000000..378d77d
--- /dev/null
@@ -0,0 +1,156 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.RESOURCE_LINK;
+import static org.onap.so.aaisimulator.utils.Constants.RESOURCE_TYPE;
+import static org.onap.so.aaisimulator.utils.Constants.SERVICE_RESOURCE_TYPE;
+import static org.onap.so.aaisimulator.utils.TestConstants.CUSTOMERS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNFS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_SUBSCRIPTIONS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.VNF_ID;
+import java.io.IOException;
+import java.util.Map;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.GenericVnf;
+import org.onap.aai.domain.yang.GenericVnfs;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.CustomerCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.NodesCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.TestConstants;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class NodesControllerTest extends AbstractSpringBootTest {
+
+    @Autowired
+    private NodesCacheServiceProvider nodesCacheServiceProvider;
+
+    @Autowired
+    private CustomerCacheServiceProvider customerCacheServiceProvider;
+
+    @After
+    public void after() {
+        nodesCacheServiceProvider.clearAll();
+        customerCacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_getNodesSericeInstance_usingServiceInstanceId_ableToRetrieveServiceInstanceFromCache()
+            throws Exception {
+
+        invokeCustomerandServiceInstanceUrls();
+
+        final ResponseEntity<ServiceInstance> actual = testRestTemplateService
+                .invokeHttpGet(getUrl(TestConstants.NODES_URL, SERVICE_INSTANCE_URL), ServiceInstance.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final ServiceInstance actualServiceInstance = actual.getBody();
+
+        assertEquals(SERVICE_NAME, actualServiceInstance.getServiceInstanceName());
+        assertEquals(SERVICE_INSTANCE_ID, actualServiceInstance.getServiceInstanceId());
+
+    }
+
+    @Test
+    public void test_getNodesSericeInstance_usingServiceInstanceIdAndFormatPathed_ableToRetrieveServiceInstanceFromCache()
+            throws Exception {
+
+        invokeCustomerandServiceInstanceUrls();
+
+        final ResponseEntity<Results> actual = testRestTemplateService.invokeHttpGet(
+                getUrl(TestConstants.NODES_URL, SERVICE_INSTANCE_URL) + "?format=" + Format.PATHED.getValue(),
+                Results.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final Results result = actual.getBody();
+
+        assertNotNull(result.getValues());
+        assertFalse(result.getValues().isEmpty());
+        final Map<String, Object> actualMap = result.getValues().get(0);
+
+        assertEquals(CUSTOMERS_URL + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCE_URL, actualMap.get(RESOURCE_LINK));
+        assertEquals(SERVICE_RESOURCE_TYPE, actualMap.get(RESOURCE_TYPE));
+
+    }
+
+    @Test
+    public void test_getNodesGenericVnfs_usingVnfName_ableToRetrieveItFromCache() throws Exception {
+        invokeCustomerandServiceInstanceUrls();
+
+        final String genericVnfUrl = getUrl(GENERIC_VNF_URL, VNF_ID);
+        final ResponseEntity<Void> genericVnfResponse =
+                testRestTemplateService.invokeHttpPut(genericVnfUrl, TestUtils.getGenericVnf(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, genericVnfResponse.getStatusCode());
+
+        final String nodeGenericVnfsUrl =
+                getUrl(TestConstants.NODES_URL, GENERIC_VNFS_URL) + "?vnf-name=" + GENERIC_VNF_NAME;
+
+        final ResponseEntity<GenericVnfs> actual =
+                testRestTemplateService.invokeHttpGet(nodeGenericVnfsUrl, GenericVnfs.class);
+
+        assertEquals(HttpStatus.OK, actual.getStatusCode());
+        assertTrue(actual.hasBody());
+
+        final GenericVnfs genericVnfs = actual.getBody();
+        assertEquals(1, genericVnfs.getGenericVnf().size());
+
+        final GenericVnf genericVnf = genericVnfs.getGenericVnf().get(0);
+        assertEquals(GENERIC_VNF_NAME, genericVnf.getVnfName());
+        assertEquals(VNF_ID, genericVnf.getVnfId());
+
+    }
+
+    private void invokeCustomerandServiceInstanceUrls() throws Exception, IOException {
+        final String url = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+
+        final ResponseEntity<Void> response =
+                testRestTemplateService.invokeHttpPut(getUrl(CUSTOMERS_URL), TestUtils.getCustomer(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+
+        final ResponseEntity<Void> response2 =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getServiceInstance(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, response2.getStatusCode());
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/OwningEntityControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/OwningEntityControllerTest.java
new file mode 100755 (executable)
index 0000000..015994a
--- /dev/null
@@ -0,0 +1,199 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.CUSTOMERS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GLOBAL_CUSTOMER_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_SUBSCRIPTIONS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_TYPE;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.OwningEntity;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.CustomerCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.OwnEntityCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.aaisimulator.utils.TestConstants;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class OwningEntityControllerTest extends AbstractSpringBootTest {
+
+    private static final String OWN_ENTITY_ID_VALUE = "oe_1";
+    private static final String OWN_ENTITY_NAME_VALUE = "oe_2";
+
+    @Autowired
+    private OwnEntityCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    private CustomerCacheServiceProvider customerCacheServiceProvider;
+
+    @After
+    public void after() {
+        cacheServiceProvider.clearAll();
+        customerCacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_putOwningEntity_successfullyAddedToCache() throws Exception {
+        final String url = getUrl(TestConstants.OWNING_ENTITY_URL, OWN_ENTITY_ID_VALUE);
+        final ResponseEntity<Void> actual =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getOwningEntity(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, actual.getStatusCode());
+
+        final ResponseEntity<OwningEntity> actualResponse =
+                testRestTemplateService.invokeHttpGet(url, OwningEntity.class);
+
+        assertEquals(HttpStatus.OK, actualResponse.getStatusCode());
+        assertTrue(actualResponse.hasBody());
+        final OwningEntity actualOwningEntity = actualResponse.getBody();
+        assertEquals(OWN_ENTITY_ID_VALUE, actualOwningEntity.getOwningEntityId());
+        assertEquals(OWN_ENTITY_NAME_VALUE, actualOwningEntity.getOwningEntityName());
+        assertNotNull(actualOwningEntity.getResourceVersion());
+
+    }
+
+    @Test
+    public void test_getOwningEntityCount_correctResult() throws Exception {
+        final String url = getUrl(TestConstants.OWNING_ENTITY_URL, OWN_ENTITY_ID_VALUE);
+        final ResponseEntity<Void> actual =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getOwningEntity(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, actual.getStatusCode());
+
+        final ResponseEntity<Results> actualResponse = testRestTemplateService
+                .invokeHttpGet(url + "?resultIndex=0&resultSize=1&format=" + Format.COUNT.getValue(), Results.class);
+
+        assertEquals(HttpStatus.OK, actualResponse.getStatusCode());
+        assertTrue(actualResponse.hasBody());
+        final Results result = actualResponse.getBody();
+        assertNotNull(result.getValues());
+        assertFalse(result.getValues().isEmpty());
+        assertEquals(1, result.getValues().get(0).get(Constants.OWNING_ENTITY));
+    }
+
+    @Test
+    public void test_putOwningEntityRelationShip_successfullyAddedToCache() throws Exception {
+        addCustomerAndServiceInstance();
+
+        final String url = getUrl(TestConstants.OWNING_ENTITY_URL, OWN_ENTITY_ID_VALUE);
+        final ResponseEntity<Void> actual =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getOwningEntity(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, actual.getStatusCode());
+
+        final String owningEntityRelationshipUrl = url + RELATIONSHIP_LIST_RELATIONSHIP_URL;
+
+        final ResponseEntity<Void> putResponse = testRestTemplateService.invokeHttpPut(owningEntityRelationshipUrl,
+                TestUtils.getOwningEntityRelationship(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, putResponse.getStatusCode());
+
+        final ResponseEntity<OwningEntity> actualResponse =
+                testRestTemplateService.invokeHttpGet(url, OwningEntity.class);
+
+        assertEquals(HttpStatus.OK, actualResponse.getStatusCode());
+        assertTrue(actualResponse.hasBody());
+        final OwningEntity actualOwningEntity = actualResponse.getBody();
+        assertEquals(OWN_ENTITY_ID_VALUE, actualOwningEntity.getOwningEntityId());
+        assertEquals(OWN_ENTITY_NAME_VALUE, actualOwningEntity.getOwningEntityName());
+        assertNotNull(actualOwningEntity.getRelationshipList());
+        assertFalse(actualOwningEntity.getRelationshipList().getRelationship().isEmpty());
+        assertNotNull(actualOwningEntity.getRelationshipList().getRelationship().get(0));
+
+        final Relationship actualRelationship = actualOwningEntity.getRelationshipList().getRelationship().get(0);
+        final List<RelationshipData> relationshipDataList = actualRelationship.getRelationshipData();
+        assertEquals(Constants.BELONGS_TO, actualRelationship.getRelationshipLabel());
+        assertFalse(relationshipDataList.isEmpty());
+        assertEquals(3, relationshipDataList.size());
+
+        final RelationshipData globalRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.CUSTOMER_GLOBAL_CUSTOMER_ID);
+        assertNotNull(globalRelationshipData);
+        assertEquals(GLOBAL_CUSTOMER_ID, globalRelationshipData.getRelationshipValue());
+
+        final RelationshipData serviceSubscriptionRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.SERVICE_SUBSCRIPTION_SERVICE_TYPE);
+        assertNotNull(serviceSubscriptionRelationshipData);
+        assertEquals(SERVICE_TYPE, serviceSubscriptionRelationshipData.getRelationshipValue());
+
+        final RelationshipData serviceInstanceRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.SERVICE_INSTANCE_SERVICE_INSTANCE_ID);
+        assertNotNull(serviceInstanceRelationshipData);
+        assertEquals(SERVICE_INSTANCE_ID, serviceInstanceRelationshipData.getRelationshipValue());
+
+        final Optional<ServiceInstance> optional =
+                customerCacheServiceProvider.getServiceInstance(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, SERVICE_INSTANCE_ID);
+        assertTrue(optional.isPresent());
+
+        final ServiceInstance serviceInstance = optional.get();
+
+        assertNotNull(serviceInstance.getRelationshipList());
+        final List<Relationship> serviceRelationshipList = serviceInstance.getRelationshipList().getRelationship();
+        assertFalse(serviceRelationshipList.isEmpty());
+        assertEquals(1, serviceRelationshipList.size());
+        final Relationship relationship = serviceRelationshipList.get(0);
+        assertEquals(Constants.BELONGS_TO, relationship.getRelationshipLabel());
+        assertEquals(TestConstants.OWNING_ENTITY_URL + OWN_ENTITY_ID_VALUE, relationship.getRelatedLink());
+
+        final List<RelationshipData> serviceRelationshipDataList = serviceRelationshipList.get(0).getRelationshipData();
+        assertFalse(serviceRelationshipDataList.isEmpty());
+        assertEquals(1, serviceRelationshipDataList.size());
+
+        final RelationshipData owningEntityRelationshipData =
+                getRelationshipData(serviceRelationshipDataList, Constants.OWNING_ENTITY_OWNING_ENTITY_ID);
+        assertNotNull(owningEntityRelationshipData);
+        assertEquals(OWN_ENTITY_ID_VALUE, owningEntityRelationshipData.getRelationshipValue());
+
+    }
+
+    private void addCustomerAndServiceInstance() throws Exception, IOException {
+        final ResponseEntity<Void> customerResponse =
+                testRestTemplateService.invokeHttpPut(getUrl(CUSTOMERS_URL), TestUtils.getCustomer(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, customerResponse.getStatusCode());
+
+        final String serviceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+        final ResponseEntity<Void> serviceInstanceResponse =
+                testRestTemplateService.invokeHttpPut(serviceInstanceUrl, TestUtils.getServiceInstance(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, serviceInstanceResponse.getStatusCode());
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/PlatformControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/PlatformControllerTest.java
new file mode 100755 (executable)
index 0000000..7e88eec
--- /dev/null
@@ -0,0 +1,142 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.BI_DIRECTIONAL_RELATIONSHIP_LIST_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GENERIC_VNF_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.PLATFORM_NAME;
+import static org.onap.so.aaisimulator.utils.TestConstants.VNF_ID;
+import java.util.List;
+import java.util.Optional;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.Platform;
+import org.onap.aai.domain.yang.RelatedToProperty;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.so.aaisimulator.models.Format;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.PlatformCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.aaisimulator.utils.TestConstants;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class PlatformControllerTest extends AbstractSpringBootTest {
+
+    @Autowired
+    private PlatformCacheServiceProvider platformCacheServiceProvider;
+
+    @After
+    public void after() {
+        platformCacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_putPlatform_successfullyAddedToCache() throws Exception {
+
+        final String platformUrl = getUrl(TestConstants.PLATFORMS_URL, PLATFORM_NAME);
+        final ResponseEntity<Void> platformResponse =
+                testRestTemplateService.invokeHttpPut(platformUrl, TestUtils.getPlatform(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, platformResponse.getStatusCode());
+
+        final ResponseEntity<Platform> response = testRestTemplateService.invokeHttpGet(platformUrl, Platform.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final Platform actualPlatform = response.getBody();
+        assertEquals(PLATFORM_NAME, actualPlatform.getPlatformName());
+        assertNotNull("resource version should not be null", actualPlatform.getResourceVersion());
+
+    }
+
+    @Test
+    public void test_getPlatformWithFormatCount() throws Exception {
+
+        final String platformUrl = getUrl(TestConstants.PLATFORMS_URL, PLATFORM_NAME);
+
+        final ResponseEntity<Void> platformResponse =
+                testRestTemplateService.invokeHttpPut(platformUrl, TestUtils.getPlatform(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, platformResponse.getStatusCode());
+
+        final ResponseEntity<Results> response = testRestTemplateService.invokeHttpGet(
+                platformUrl + "?resultIndex=0&resultSize=1&format=" + Format.COUNT.getValue(), Results.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final Results result = response.getBody();
+        assertNotNull(result.getValues());
+        assertFalse(result.getValues().isEmpty());
+        assertEquals(1, result.getValues().get(0).get(Constants.PLATFORM));
+
+    }
+
+    @Test
+    public void test_putGenericVnfRelationShipToPlatform_successfullyAddedToCache() throws Exception {
+
+        final String platformUrl = getUrl(TestConstants.PLATFORMS_URL, PLATFORM_NAME);
+        final ResponseEntity<Void> platformResponse =
+                testRestTemplateService.invokeHttpPut(platformUrl, TestUtils.getPlatform(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, platformResponse.getStatusCode());
+
+        final String platformRelationShipUrl =
+                getUrl(TestConstants.PLATFORMS_URL, PLATFORM_NAME, BI_DIRECTIONAL_RELATIONSHIP_LIST_URL);
+
+        final ResponseEntity<Relationship> responseEntity = testRestTemplateService
+                .invokeHttpPut(platformRelationShipUrl, TestUtils.getGenericVnfRelationShip(), Relationship.class);
+        assertEquals(HttpStatus.ACCEPTED, responseEntity.getStatusCode());
+
+        final Optional<Platform> optional = platformCacheServiceProvider.getPlatform(PLATFORM_NAME);
+        assertTrue(optional.isPresent());
+
+        final Platform actual = optional.get();
+
+        assertNotNull(actual.getRelationshipList());
+        final List<Relationship> relationshipList = actual.getRelationshipList().getRelationship();
+        assertFalse("Relationship list should not be empty", relationshipList.isEmpty());
+        final Relationship relationship = relationshipList.get(0);
+
+        assertEquals(GENERIC_VNF_URL + VNF_ID, relationship.getRelatedLink());
+        assertFalse("RelationshipData list should not be empty", relationship.getRelationshipData().isEmpty());
+        assertFalse("RelatedToProperty list should not be empty", relationship.getRelatedToProperty().isEmpty());
+
+        final RelationshipData relationshipData = relationship.getRelationshipData().get(0);
+        assertEquals(Constants.GENERIC_VNF_VNF_ID, relationshipData.getRelationshipKey());
+        assertEquals(TestConstants.VNF_ID, relationshipData.getRelationshipValue());
+
+        final RelatedToProperty relatedToProperty = relationship.getRelatedToProperty().get(0);
+        assertEquals(Constants.GENERIC_VNF_VNF_NAME, relatedToProperty.getPropertyKey());
+        assertEquals(TestConstants.GENERIC_VNF_NAME, relatedToProperty.getPropertyValue());
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/PnfsControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/PnfsControllerTest.java
new file mode 100755 (executable)
index 0000000..10e9b66
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.v15.Pnf;
+import org.onap.so.aaisimulator.service.providers.PnfCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+/**
+ * @author Raj Gumma (raj.gumma@est.tech)
+ *
+ */
+public class PnfsControllerTest extends AbstractSpringBootTest {
+
+    @Autowired
+    private PnfCacheServiceProvider cacheServiceProvider;
+
+    private final String PNF="test-008";
+    private final String PNF_URL= "/aai/v15/network/pnfs/pnf/";
+
+
+    @After
+    public void after() {
+        cacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_pnf_successfullyAddedToCache() throws Exception {
+
+        final String url = getUrl(PNF_URL, PNF);
+        final ResponseEntity<Void> pnfResponse =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getPnf(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, pnfResponse.getStatusCode());
+
+        final ResponseEntity<Pnf> response =
+                testRestTemplateService.invokeHttpGet(url, Pnf.class);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+
+        assertTrue(response.hasBody());
+
+        final Pnf actualPnf = response.getBody();
+        assertEquals("test-008", actualPnf.getPnfName());
+        assertEquals("5f2602dc-f647-4535-8f1d-9ec079e68a49", actualPnf.getPnfId());
+
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/ProjectControllerTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/ProjectControllerTest.java
new file mode 100755 (executable)
index 0000000..678d417
--- /dev/null
@@ -0,0 +1,205 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onap.so.aaisimulator.utils.Constants.RELATIONSHIP_LIST_RELATIONSHIP_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.CUSTOMERS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.GLOBAL_CUSTOMER_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_ID;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_INSTANCE_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_SUBSCRIPTIONS_URL;
+import static org.onap.so.aaisimulator.utils.TestConstants.SERVICE_TYPE;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import org.junit.After;
+import org.junit.Test;
+import org.onap.aai.domain.yang.Project;
+import org.onap.aai.domain.yang.Relationship;
+import org.onap.aai.domain.yang.RelationshipData;
+import org.onap.aai.domain.yang.ServiceInstance;
+import org.onap.so.aaisimulator.models.Results;
+import org.onap.so.aaisimulator.service.providers.CustomerCacheServiceProvider;
+import org.onap.so.aaisimulator.service.providers.ProjectCacheServiceProvider;
+import org.onap.so.aaisimulator.utils.Constants;
+import org.onap.so.aaisimulator.utils.TestConstants;
+import org.onap.so.aaisimulator.utils.TestRestTemplateService;
+import org.onap.so.aaisimulator.utils.TestUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.server.LocalServerPort;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class ProjectControllerTest extends AbstractSpringBootTest {
+
+    private static final String PROJECT_NAME_VALUE = "PROJECT_NAME_VALUE";
+
+    @LocalServerPort
+    private int port;
+
+    @Autowired
+    private TestRestTemplateService testRestTemplateService;
+
+    @Autowired
+    private ProjectCacheServiceProvider cacheServiceProvider;
+
+    @Autowired
+    private CustomerCacheServiceProvider customerCacheServiceProvider;
+
+    @After
+    public void after() {
+        cacheServiceProvider.clearAll();
+        customerCacheServiceProvider.clearAll();
+    }
+
+    @Test
+    public void test_putProject_successfullyAddedToCache() throws Exception {
+        final String url = getUrl(TestConstants.PROJECT_URL, PROJECT_NAME_VALUE);
+        final ResponseEntity<Void> actual =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getBusinessProject(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, actual.getStatusCode());
+
+        final ResponseEntity<Project> actualResponse = testRestTemplateService.invokeHttpGet(url, Project.class);
+
+        assertEquals(HttpStatus.OK, actualResponse.getStatusCode());
+        assertTrue(actualResponse.hasBody());
+        final Project actualProject = actualResponse.getBody();
+        assertEquals(PROJECT_NAME_VALUE, actualProject.getProjectName());
+        assertNotNull(actualProject.getResourceVersion());
+
+    }
+
+    @Test
+    public void test_putProjectRelationShip_successfullyAddedToCache() throws Exception {
+        addCustomerAndServiceInstance();
+
+        final String url = getUrl(TestConstants.PROJECT_URL, PROJECT_NAME_VALUE);
+        final ResponseEntity<Void> actual =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getBusinessProject(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, actual.getStatusCode());
+
+        final String projectRelationshipUrl =
+                getUrl(TestConstants.PROJECT_URL, PROJECT_NAME_VALUE, RELATIONSHIP_LIST_RELATIONSHIP_URL);
+
+        final ResponseEntity<Void> putResponse = testRestTemplateService.invokeHttpPut(projectRelationshipUrl,
+                TestUtils.getBusinessProjectRelationship(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, putResponse.getStatusCode());
+
+        final ResponseEntity<Project> actualResponse = testRestTemplateService.invokeHttpGet(url, Project.class);
+
+        assertEquals(HttpStatus.OK, actualResponse.getStatusCode());
+        assertTrue(actualResponse.hasBody());
+        final Project actualProject = actualResponse.getBody();
+        assertEquals(PROJECT_NAME_VALUE, actualProject.getProjectName());
+        assertNotNull(actualProject.getRelationshipList());
+        assertFalse(actualProject.getRelationshipList().getRelationship().isEmpty());
+        assertNotNull(actualProject.getRelationshipList().getRelationship().get(0));
+
+        final Relationship actualRelationship = actualProject.getRelationshipList().getRelationship().get(0);
+        final List<RelationshipData> relationshipDataList = actualRelationship.getRelationshipData();
+        assertEquals(Constants.USES, actualRelationship.getRelationshipLabel());
+
+        assertFalse(relationshipDataList.isEmpty());
+        assertEquals(3, relationshipDataList.size());
+
+        final RelationshipData globalRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.CUSTOMER_GLOBAL_CUSTOMER_ID);
+        assertNotNull(globalRelationshipData);
+        assertEquals(GLOBAL_CUSTOMER_ID, globalRelationshipData.getRelationshipValue());
+
+        final RelationshipData serviceSubscriptionRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.SERVICE_SUBSCRIPTION_SERVICE_TYPE);
+        assertNotNull(serviceSubscriptionRelationshipData);
+        assertEquals(SERVICE_TYPE, serviceSubscriptionRelationshipData.getRelationshipValue());
+
+        final RelationshipData serviceInstanceRelationshipData =
+                getRelationshipData(relationshipDataList, Constants.SERVICE_INSTANCE_SERVICE_INSTANCE_ID);
+        assertNotNull(serviceInstanceRelationshipData);
+        assertEquals(SERVICE_INSTANCE_ID, serviceInstanceRelationshipData.getRelationshipValue());
+
+        final Optional<ServiceInstance> optional =
+                customerCacheServiceProvider.getServiceInstance(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, SERVICE_INSTANCE_ID);
+        assertTrue(optional.isPresent());
+
+        final ServiceInstance serviceInstance = optional.get();
+
+        assertNotNull(serviceInstance.getRelationshipList());
+        final List<Relationship> serviceRelationshipList = serviceInstance.getRelationshipList().getRelationship();
+        assertFalse(serviceRelationshipList.isEmpty());
+        assertEquals(1, serviceRelationshipList.size());
+        final Relationship relationship = serviceRelationshipList.get(0);
+        assertEquals(Constants.USES, relationship.getRelationshipLabel());
+        assertEquals(TestConstants.PROJECT_URL + PROJECT_NAME_VALUE, relationship.getRelatedLink());
+
+
+        final List<RelationshipData> serviceRelationshipDataList = serviceRelationshipList.get(0).getRelationshipData();
+        assertFalse(serviceRelationshipDataList.isEmpty());
+        assertEquals(1, serviceRelationshipDataList.size());
+
+        final RelationshipData projectRelationshipData =
+                getRelationshipData(serviceRelationshipDataList, Constants.PROJECT_PROJECT_NAME);
+        assertNotNull(projectRelationshipData);
+        assertEquals(PROJECT_NAME_VALUE, projectRelationshipData.getRelationshipValue());
+
+    }
+
+    @Test
+    public void test_getProjectCount_correctResult() throws Exception {
+        final String url = getUrl(TestConstants.PROJECT_URL, PROJECT_NAME_VALUE);
+        final ResponseEntity<Void> actual =
+                testRestTemplateService.invokeHttpPut(url, TestUtils.getBusinessProject(), Void.class);
+
+        assertEquals(HttpStatus.ACCEPTED, actual.getStatusCode());
+
+        final ResponseEntity<Results> actualResponse =
+                testRestTemplateService.invokeHttpGet(url + "?resultIndex=0&resultSize=1&format=count", Results.class);
+
+        assertEquals(HttpStatus.OK, actualResponse.getStatusCode());
+        assertTrue(actualResponse.hasBody());
+        final Results result = actualResponse.getBody();
+        assertNotNull(result.getValues());
+        assertFalse(result.getValues().isEmpty());
+        assertEquals(1, result.getValues().get(0).get(Constants.PROJECT));
+    }
+
+
+    private void addCustomerAndServiceInstance() throws Exception, IOException {
+        final ResponseEntity<Void> customerResponse =
+                testRestTemplateService.invokeHttpPut(getUrl(CUSTOMERS_URL), TestUtils.getCustomer(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, customerResponse.getStatusCode());
+
+        final String serviceInstanceUrl = getUrl(CUSTOMERS_URL, SERVICE_SUBSCRIPTIONS_URL, SERVICE_INSTANCE_URL);
+        final ResponseEntity<Void> serviceInstanceResponse =
+                testRestTemplateService.invokeHttpPut(serviceInstanceUrl, TestUtils.getServiceInstance(), Void.class);
+        assertEquals(HttpStatus.ACCEPTED, serviceInstanceResponse.getStatusCode());
+
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/configuration/TestRestTemplateConfigration.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/configuration/TestRestTemplateConfigration.java
new file mode 100755 (executable)
index 0000000..92036e8
--- /dev/null
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.controller.configuration;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContexts;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+@Profile("test")
+@Configuration
+public class TestRestTemplateConfigration {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(TestRestTemplateConfigration.class);
+
+    @Bean
+    public TestRestTemplate testRestTemplate() throws Exception {
+        final TestRestTemplate testRestTemplate = new TestRestTemplate();
+        ((HttpComponentsClientHttpRequestFactory) testRestTemplate.getRestTemplate().getRequestFactory())
+                .setHttpClient(httpClient());
+        return testRestTemplate;
+
+    }
+
+    @Bean
+    public RestTemplate restTemplate() throws Exception {
+        final RestTemplate restTemplate = new RestTemplate();
+        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient()));
+        return restTemplate;
+    }
+
+    private CloseableHttpClient httpClient() throws Exception {
+        final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
+
+        final SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(
+                SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(), new HostnameVerifier() {
+                    @Override
+                    public boolean verify(final String hostname, final SSLSession session) {
+                        LOGGER.warn("Skiping hostname verification ... ");
+                        return true;
+                    }
+
+                });
+
+        return HttpClients.custom().setSSLSocketFactory(csf).build();
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestConstants.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestConstants.java
new file mode 100755 (executable)
index 0000000..85ceeef
--- /dev/null
@@ -0,0 +1,118 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class TestConstants {
+
+    public static final String BASE_URL_V17 = "/aai/v17";
+
+    public static final String SERVICE_INSTANCES_URL = "/service-instances";
+
+    public static final String SERVICE_NAME = "ServiceTest";
+
+    public static final String SERVICE_INSTANCE_ID = "ccece8fe-13da-456a-baf6-41b3a4a2bc2b";
+
+    public static final String SERVICE_INSTANCE_URL =
+            SERVICE_INSTANCES_URL + "/service-instance/" + SERVICE_INSTANCE_ID;
+
+    public static final String SERVICE_TYPE = "vCPE";
+
+    public static final String SERVICE_SUBSCRIPTIONS_URL =
+            "/service-subscriptions/service-subscription/" + SERVICE_TYPE;
+
+    public static final String GLOBAL_CUSTOMER_ID = "DemoCustomer";
+
+    public static final String CUSTOMERS_URL = BASE_URL_V17 + "/business/customers/customer/" + GLOBAL_CUSTOMER_ID;
+
+    public static final String VNF_ID = "dfd02fb5-d7fb-4aac-b3c4-cd6b60058701";
+
+    public static final String GENERIC_VNF_NAME = "EsyVnfInstantiationTest2";
+
+    public static final String GENERIC_VNF_URL = BASE_URL_V17 + "/network/generic-vnfs/generic-vnf/";
+
+    public static final String GENERIC_VNFS_URL = "/generic-vnfs";
+
+    public static final String RELATED_TO_URL = "/related-to" + GENERIC_VNFS_URL;
+
+    public static final String PLATFORM_NAME = "PLATFORM_APP_ID_1";
+
+    public static final String LINE_OF_BUSINESS_NAME = "LINE_OF_BUSINESS_1";
+
+    public static final String CLOUD_OWNER_NAME = "CloudOwner";
+
+    public static final String CLOUD_REGION_NAME = "PnfSwUCloudRegion";
+
+    public static final String TENANT_ID = "693c7729b2364a26a3ca602e6f66187d";
+
+    public static final String TENANTS_TENANT = "/tenants/tenant/";
+
+    public static final String ESR_VNFM_URL = BASE_URL_V17 + "/external-system/esr-vnfm-list/esr-vnfm/";
+
+    public static final String EXTERNAL_SYSTEM_ESR_VNFM_LIST_URL = BASE_URL_V17 + "/external-system/esr-vnfm-list";
+
+    public static final String ESR_VNFM_ID = "c5e99cee-1996-4606-b697-838d51d4e1a3";
+
+    public static final String ESR_VIM_ID = "PnfSwUVimId";
+
+    public static final String ESR_SYSTEM_INFO_LIST_URL = "/esr-system-info-list";
+
+    public static final String ESR_SYSTEM_INFO_ID = "5c067098-f2e3-40f7-a7ba-155e7c61e916";
+
+    public static final String ESR_SYSTEM_TYPE = "VNFM";
+
+    public static final String ESR_PASSWORD = "123456";
+
+    public static final String ESR_USERNAME = "vnfmadapter";
+
+    public static final String ESR_SERVICE_URL = "https://so-vnfm-simulator.onap:9095/vnflcm/v1";
+
+    public static final String ESR_VENDOR = "EST";
+
+    public static final String ESR_TYEP = "simulator";
+
+    public static final String SYSTEM_NAME = "vnfmSimulator";
+
+    public static final String VSERVER_URL = "/vservers/vserver/";
+
+    public static final String VSERVER_NAME = "CsitVServer";
+
+    public static final String VSERVER_ID = "f84fdb9b-ad7c-49db-a08f-e443b4cbd033";
+
+    public static final String OWNING_ENTITY_URL = BASE_URL_V17 + "/business/owning-entities/owning-entity/";
+
+    public static final String LINES_OF_BUSINESS_URL = BASE_URL_V17 + "/business/lines-of-business/line-of-business/";
+
+    public static final String PLATFORMS_URL = BASE_URL_V17 + "/business/platforms/platform/";
+
+    public static final String CLOUD_REGIONS = BASE_URL_V17 + "/cloud-infrastructure/cloud-regions/cloud-region/";
+
+    public static final String GENERIC_VNFS_URL_1 = BASE_URL_V17 + "/network/generic-vnfs";
+
+    public static final String NODES_URL = BASE_URL_V17 + "/nodes";
+
+    public static final String PROJECT_URL = BASE_URL_V17 + "/business/projects/project/";
+
+    private TestConstants() {}
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestRestTemplateService.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestRestTemplateService.java
new file mode 100755 (executable)
index 0000000..e49e6d4
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+import org.onap.so.simulator.model.UserCredentials;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+
+@Service
+public class TestRestTemplateService {
+
+    @Autowired
+    private TestRestTemplate restTemplate;
+
+    @Autowired
+    private UserCredentials userCredentials;
+
+
+    public <T> ResponseEntity<T> invokeHttpGet(final String url, final Class<T> clazz) {
+        return restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(getHttpHeaders()), clazz);
+    }
+
+    public <T> ResponseEntity<T> invokeHttpPut(final String url, final Object obj, final Class<T> clazz) {
+        final HttpEntity<?> httpEntity = getHttpEntity(obj);
+        return restTemplate.exchange(url, HttpMethod.PUT, httpEntity, clazz);
+    }
+
+    public <T> ResponseEntity<T> invokeHttpDelete(final String url, final Class<T> clazz) {
+        final HttpEntity<?> request = new HttpEntity<>(getHttpHeaders());
+        return restTemplate.exchange(url, HttpMethod.DELETE, request, clazz);
+    }
+
+    public <T> ResponseEntity<T> invokeHttpPost(final String url, final Object obj, final Class<T> clazz) {
+        final HttpEntity<?> httpEntity = getHttpEntity(obj);
+        return restTemplate.exchange(url, HttpMethod.POST, httpEntity, clazz);
+    }
+
+    public <T> ResponseEntity<T> invokeHttpPost(final HttpHeaders headers, final String url, final Object obj,
+            final Class<T> clazz) {
+        final HttpEntity<Object> entity = new HttpEntity<>(obj, headers);
+        return restTemplate.exchange(url, HttpMethod.POST, entity, clazz);
+    }
+
+    private HttpEntity<?> getHttpEntity(final Object obj) {
+        return new HttpEntity<>(obj, getHttpHeaders());
+    }
+
+    public HttpHeaders getHttpHeaders() {
+        return TestUtils.getHttpHeaders(userCredentials.getUsers().iterator().next().getUsername());
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestUtils.java b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestUtils.java
new file mode 100755 (executable)
index 0000000..55eb0ef
--- /dev/null
@@ -0,0 +1,186 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.aaisimulator.utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Base64;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.web.util.UriComponentsBuilder;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public class TestUtils {
+
+    private static final String PASSWORD = "aai.onap.org:demo123456!";
+
+    public static HttpHeaders getHttpHeaders(final String username) {
+        final HttpHeaders requestHeaders = new HttpHeaders();
+        requestHeaders.add("Authorization", getBasicAuth(username));
+        requestHeaders.setContentType(MediaType.APPLICATION_JSON);
+        return requestHeaders;
+    }
+
+    public static File getFile(final String file) throws IOException {
+        return new ClassPathResource(file).getFile();
+    }
+
+    public static String getJsonString(final String file) throws IOException {
+        return new String(Files.readAllBytes(getFile(file).toPath()));
+    }
+
+    public static <T> T getObjectFromFile(final File file, final Class<T> clazz) throws Exception {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.registerModule(new JaxbAnnotationModule());
+
+        return mapper.readValue(file, clazz);
+    }
+
+    public static String getBasicAuth(final String username) {
+        return "Basic " + new String(Base64.getEncoder().encodeToString((username + ":" + PASSWORD).getBytes()));
+    }
+
+    public static String getBaseUrl(final int port) {
+        return "https://localhost:" + port;
+    }
+
+    public static String getCustomer() throws Exception, IOException {
+        return getJsonString("test-data/business-customer.json");
+    }
+
+    public static String getServiceSubscription() throws IOException {
+        return getJsonString("test-data/service-subscription.json");
+    }
+
+    public static String getServiceInstance() throws IOException {
+        return getJsonString("test-data/service-instance.json");
+    }
+
+    public static String getGenericVnf() throws IOException {
+        return getJsonString("test-data/generic-vnf.json");
+    }
+
+    public static String getPnf() throws IOException {
+        return getJsonString("test-data/pnf.json");
+    }
+
+    public static String getRelationShip() throws IOException {
+        return getJsonString("test-data/relation-ship.json");
+    }
+
+    public static String getPlatformRelatedLink() throws IOException {
+        return getJsonString("test-data/platform-related-link.json");
+    }
+
+    public static String getLineOfBusinessRelatedLink() throws IOException {
+        return getJsonString("test-data/line-of-business-related-link.json");
+    }
+
+    public static String getPlatform() throws IOException {
+        return getJsonString("test-data/platform.json");
+    }
+
+    public static String getGenericVnfRelationShip() throws IOException {
+        return getJsonString("test-data/generic-vnf-relationship.json");
+    }
+
+    public static String getLineOfBusiness() throws IOException {
+        return getJsonString("test-data/line-of-business.json");
+    }
+
+    public static String getBusinessProject() throws IOException {
+        return getJsonString("test-data/business-project.json");
+    }
+
+    public static String getBusinessProjectRelationship() throws IOException {
+        return getJsonString("test-data/business-project-relation-ship.json");
+    }
+
+    public static String getOwningEntityRelationship() throws IOException {
+        return getJsonString("test-data/owning-entity-relation-ship.json");
+    }
+
+    public static String getOwningEntity() throws IOException {
+        return getJsonString("test-data/owning-entity.json");
+    }
+
+    public static String getOrchStatuUpdateServiceInstance() throws IOException {
+        return getJsonString("test-data/service-instance-orch-status-update.json");
+    }
+
+    public static String getRelationShipJsonObject() throws IOException {
+        return getJsonString("test-data/service-Instance-relationShip.json");
+    }
+
+    public static String getCloudRegion() throws IOException {
+        return getJsonString("test-data/cloud-region.json");
+    }
+
+    public static String getTenant() throws IOException {
+        return getJsonString("test-data/tenant.json");
+    }
+
+    public static String getCloudRegionRelatedLink() throws IOException {
+        return getJsonString("test-data/cloud-region-related-link.json");
+    }
+
+    public static String getGenericVnfRelatedLink() throws IOException {
+        return getJsonString("test-data/generic-vnf-related-link.json");
+    }
+
+    public static String getTenantRelationShip() throws IOException {
+        return getJsonString("test-data/tenant-relationship.json");
+    }
+
+    public static String getGenericVnfOrchStatuUpdate() throws IOException {
+        return getJsonString("test-data/generic-vnf-orch-status-update.json");
+    }
+
+    public static String getEsrVnfm() throws IOException {
+        return getJsonString("test-data/esr-vnfm.json");
+    }
+
+    public static String getEsrSystemInfo() throws IOException {
+        return getJsonString("test-data/esr-system-info.json");
+    }
+
+    public static String getVserver() throws IOException {
+        return getJsonString("test-data/vServer.json");
+    }
+
+
+    public static String getUrl(final int port, final String... urls) {
+        final UriComponentsBuilder baseUri = UriComponentsBuilder.fromUriString("https://localhost:" + port);
+        for (final String url : urls) {
+            baseUri.path(url);
+        }
+        return baseUri.toUriString();
+    }
+
+    private TestUtils() {}
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-customer.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-customer.json
new file mode 100755 (executable)
index 0000000..6c53c05
--- /dev/null
@@ -0,0 +1,73 @@
+{
+    "global-customer-id": "DemoCustomer",
+    "subscriber-name": "DemoCustomer",
+    "subscriber-type": "INFRA",
+    "service-subscriptions": {
+        "service-subscription": [
+            {
+                "service-type": "vLB",
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "tenant",
+                            "relationship-label": "org.onap.relationships.inventory.Uses",
+                            "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/xyzcloud/tenants/tenant/693c7729b2364a26a3ca602e6f66187d",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "cloud-region.cloud-owner",
+                                    "relationship-value": "CloudOwner"
+                                },
+                                {
+                                    "relationship-key": "cloud-region.cloud-region-id",
+                                    "relationship-value": "xyzcloud"
+                                },
+                                {
+                                    "relationship-key": "tenant.tenant-id",
+                                    "relationship-value": "693c7729b2364a26a3ca602e6f66187d"
+                                }
+                            ],
+                            "related-to-property": [
+                                {
+                                    "property-key": "tenant.tenant-name",
+                                    "property-value": "admin"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            },
+            {
+                "service-type": "vCPE",
+                "relationship-list": {
+                    "relationship": [
+                        {
+                            "related-to": "tenant",
+                            "relationship-label": "org.onap.relationships.inventory.Uses",
+                            "related-link": "/aai/v14/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/xyzcloud/tenants/tenant/693c7729b2364a26a3ca602e6f66187d",
+                            "relationship-data": [
+                                {
+                                    "relationship-key": "cloud-region.cloud-owner",
+                                    "relationship-value": "CloudOwner"
+                                },
+                                {
+                                    "relationship-key": "cloud-region.cloud-region-id",
+                                    "relationship-value": "xyzcloud"
+                                },
+                                {
+                                    "relationship-key": "tenant.tenant-id",
+                                    "relationship-value": "693c7729b2364a26a3ca602e6f66187d"
+                                }
+                            ],
+                            "related-to-property": [
+                                {
+                                    "property-key": "tenant.tenant-name",
+                                    "property-value": "admin"
+                                }
+                            ]
+                        }
+                    ]
+                }
+            }
+        ]
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-project-relation-ship.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-project-relation-ship.json
new file mode 100755 (executable)
index 0000000..c266226
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "related-link": "/business/customers/customer/DemoCustomer/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/ccece8fe-13da-456a-baf6-41b3a4a2bc2b"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-project.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-project.json
new file mode 100755 (executable)
index 0000000..f78ddfa
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "project-name": "PROJECT_NAME_VALUE"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/cloud-region-related-link.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/cloud-region-related-link.json
new file mode 100755 (executable)
index 0000000..f6bf992
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "related-link": "/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/PnfSwUCloudRegion"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/cloud-region.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/cloud-region.json
new file mode 100755 (executable)
index 0000000..fa32840
--- /dev/null
@@ -0,0 +1,10 @@
+{
+    "cloud-owner": "CloudOwner",
+    "cloud-region-id": "PnfSwUCloudRegion",
+    "cloud-type": "openstack",
+    "owner-defined-type": "OwnerType",
+    "cloud-region-version": "1.0",
+    "cloud-zone": "CloudZone",
+    "complex-name": "clli1",
+    "cloud-extra-info": ""
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/esr-system-info.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/esr-system-info.json
new file mode 100755 (executable)
index 0000000..65d6095
--- /dev/null
@@ -0,0 +1,12 @@
+{
+    "esr-system-info-id": "5c067098-f2e3-40f7-a7ba-155e7c61e916",
+    "system-name": "vnfmSimulator",
+    "type": "simulator",
+    "vendor": "EST",
+    "version": "V1.0",
+    "service-url": "https://so-vnfm-simulator.onap:9095/vnflcm/v1",
+    "user-name": "vnfmadapter",
+    "password": "123456",
+    "system-type": "VNFM",
+    "resource-version": "1564774459055"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/esr-vnfm.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/esr-vnfm.json
new file mode 100755 (executable)
index 0000000..5239527
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "vnfm-id": "c5e99cee-1996-4606-b697-838d51d4e1a3",
+    "vim-id": "PnfSwUVimId",
+    "certificate-url": ""
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-orch-status-update.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-orch-status-update.json
new file mode 100755 (executable)
index 0000000..2c00ea3
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "vnf-id": "dfd02fb5-d7fb-4aac-b3c4-cd6b60058701",
+    "orchestration-status": "Assigned"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-related-link.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-related-link.json
new file mode 100755 (executable)
index 0000000..388773b
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "related-link": "/network/generic-vnfs/generic-vnf/dfd02fb5-d7fb-4aac-b3c4-cd6b60058701"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-relationship.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-relationship.json
new file mode 100755 (executable)
index 0000000..25f317a
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "related-to": "generic-vnf",
+    "relationship-label": "org.onap.relationships.inventory.Uses",
+    "related-link": "/aai/v17/network/generic-vnfs/generic-vnf/dfd02fb5-d7fb-4aac-b3c4-cd6b60058701",
+    "relationship-data": [{
+        "relationship-key": "generic-vnf.vnf-id",
+        "relationship-value": "dfd02fb5-d7fb-4aac-b3c4-cd6b60058701"
+    }],
+    "related-to-property": [{
+        "property-key": "generic-vnf.vnf-name",
+        "property-value": "EsyVnfInstantiationTest2"
+    }]
+}
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf.json
new file mode 100755 (executable)
index 0000000..3740ce1
--- /dev/null
@@ -0,0 +1,14 @@
+{
+    "vnf-id": "dfd02fb5-d7fb-4aac-b3c4-cd6b60058701",
+    "vnf-name": "EsyVnfInstantiationTest2",
+    "vnf-type": "Sol004Zip4Service/Sol004Zip3VSP 0",
+    "service-id": "f13844f4-dbf8-4d0e-a979-45204f3ddb4e",
+    "prov-status": "PREPROV",
+    "orchestration-status": "Inventoried",
+    "model-invariant-id": "b0f14066-2b65-40d2-b5a4-c8f2116fb5fc",
+    "model-version-id": "84b9649a-4eb9-4967-9abe-e8702f55518b",
+    "model-customization-id": "50a90cd7-a84e-4ee1-b5ba-bfa5a26f5e15",
+    "nf-type": "vnflcm",
+    "nf-role": "vnflcm",
+    "selflink": "http://localhost:9921/generic-vnf/dfd02fb5-d7fb-4aac-b3c4-cd6b60058701"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/line-of-business-related-link.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/line-of-business-related-link.json
new file mode 100755 (executable)
index 0000000..5ec5e9f
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "related-link": "/business/lines-of-business/line-of-business/LINE_OF_BUSINESS_1"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/line-of-business.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/line-of-business.json
new file mode 100755 (executable)
index 0000000..61746a2
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "line-of-business-name": "LINE_OF_BUSINESS_1"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/owning-entity-relation-ship.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/owning-entity-relation-ship.json
new file mode 100755 (executable)
index 0000000..c266226
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "related-link": "/business/customers/customer/DemoCustomer/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/ccece8fe-13da-456a-baf6-41b3a4a2bc2b"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/owning-entity.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/owning-entity.json
new file mode 100755 (executable)
index 0000000..7248d41
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "owning-entity-id": "oe_1",
+    "owning-entity-name": "oe_2"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/platform-related-link.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/platform-related-link.json
new file mode 100755 (executable)
index 0000000..6e0de8e
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "related-link": "/business/platforms/platform/PLATFORM_APP_ID_1"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/platform.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/platform.json
new file mode 100755 (executable)
index 0000000..d94f2f0
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "platform-name": "PLATFORM_APP_ID_1"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/pnf.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/pnf.json
new file mode 100755 (executable)
index 0000000..fdd865d
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "pnf-name2":"example-pnf-name2-val-78244",
+  "pnf-name2-source":"example-pnf-name2-source-val-99275",
+  "equip-type":"example-equip-type-val-20348",
+  "equip-vendor":"example-equip-vendor-val-52182",
+  "equip-model":"example-equip-model-val-8370",
+  "management-option":"example-management-option-val-72881",
+  "ipaddress-v4-oam":"10.12.25.73",
+  "ipaddress-v6-oam":"x:x:x:x:x:X",
+  "target-software-version":"xxxxXXX",
+  "pnf-name":"test-008",
+  "pnf-id":"5f2602dc-f647-4535-8f1d-9ec079e68a49",
+  "in-maint":false,
+  "resource-version":"1570117118905",
+  "selflink": "http://localhost:9921/pnf/test-008"
+}
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/relation-ship.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/relation-ship.json
new file mode 100755 (executable)
index 0000000..c266226
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "related-link": "/business/customers/customer/DemoCustomer/service-subscriptions/service-subscription/vCPE/service-instances/service-instance/ccece8fe-13da-456a-baf6-41b3a4a2bc2b"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-Instance-relationShip.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-Instance-relationShip.json
new file mode 100755 (executable)
index 0000000..ab643d3
--- /dev/null
@@ -0,0 +1,13 @@
+{
+    "related-to": "generic-vnf",
+    "relationship-label": "org.onap.relationships.inventory.ComposedOf",
+    "related-link": "/aai/v15/network/generic-vnfs/generic-vnf/dfd02fb5-d7fb-4aac-b3c4-cd6b60058701",
+    "relationship-data": [{
+        "relationship-key": "generic-vnf.vnf-id",
+        "relationship-value": "dfd02fb5-d7fb-4aac-b3c4-cd6b60058701"
+    }],
+    "related-to-property": [{
+        "property-key": "generic-vnf.vnf-name",
+        "property-value": "EsyVnfInstantiationTest2"
+    }]
+}
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-instance-orch-status-update.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-instance-orch-status-update.json
new file mode 100755 (executable)
index 0000000..5cd566a
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "service-instance-id": "ccece8fe-13da-456a-baf6-41b3a4a2bc2b",
+    "service-instance-name": "ServiceTest",
+    "orchestration-status": "Active"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-instance.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-instance.json
new file mode 100755 (executable)
index 0000000..18ae8cb
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "service-instance-id": "ccece8fe-13da-456a-baf6-41b3a4a2bc2b",
+    "service-instance-name": "ServiceTest",
+    "environment-context": "General_Revenue-Bearing",
+    "workload-context": "Production",
+    "model-invariant-id": "e9acd081-9c89-4b4d-bcb3-e0e2b9715b2a",
+    "model-version-id": "c112a499-6148-488b-ba82-3f5938cf26d2",
+    "orchestration-status": "Inventoried"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-subscription.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-subscription.json
new file mode 100755 (executable)
index 0000000..e1b4f4f
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "service-type": "Firewall"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/tenant-relationship.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/tenant-relationship.json
new file mode 100755 (executable)
index 0000000..eb96c8c
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    "related-to": "tenant",
+    "relationship-label": "org.onap.relationships.inventory.BelongsTo",
+    "related-link": "/aai/v15/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/PnfSwUCloudRegion/tenants/tenant/693c7729b2364a26a3ca602e6f66187d",
+    "relationship-data": [
+        {
+            "relationship-key": "cloud-region.cloud-owner",
+            "relationship-value": "CloudOwner"
+        },
+        {
+            "relationship-key": "cloud-region.cloud-region-id",
+            "relationship-value": "PnfSwUCloudRegion"
+        },
+        {
+            "relationship-key": "tenant.tenant-id",
+            "relationship-value": "693c7729b2364a26a3ca602e6f66187d"
+        }
+    ],
+    "related-to-property": [
+        {
+            "property-key": "tenant.tenant-name",
+            "property-value": "admin"
+        }
+    ]
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/tenant.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/tenant.json
new file mode 100755 (executable)
index 0000000..746131a
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "tenant-id": "693c7729b2364a26a3ca602e6f66187d",
+    "tenant-name": "admin"
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/vServer.json b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/vServer.json
new file mode 100755 (executable)
index 0000000..5fa1843
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    "vserver-id": "f84fdb9b-ad7c-49db-a08f-e443b4cbd033",
+    "vserver-name": "CsitVServer",
+    "prov-status": "active",
+    "relationship-list": {
+        "relationship": [
+            {
+                "related-to": "generic-vnf",
+                "relationship-label": "tosca.relationships.HostedOn",
+                "related-link": "/aai/v15/network/generic-vnfs/generic-vnf/dfd02fb5-d7fb-4aac-b3c4-cd6b60058701",
+                "relationship-data": [
+                    {
+                        "relationship-key": "generic-vnf.vnf-id",
+                        "relationship-value": "58157d7e-d50d-4a7d-aebe-ae6e41ca1d9f"
+                    }
+                ],
+                "related-to-property": [
+                    {
+                        "property-key": "generic-vnf.vnf-name",
+                        "property-value": "Test"
+                    }
+                ]
+            }
+        ]
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/common/pom.xml b/plans/usecases/pnf-sw-upgrade/so/simulator/common/pom.xml
new file mode 100755 (executable)
index 0000000..340894e
--- /dev/null
@@ -0,0 +1,38 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onap.so.simulators</groupId>
+        <artifactId>simulator</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>common</artifactId>
+    <properties>
+        <version.equalsverifier>2.5.1</version.equalsverifier>
+        <version.openpojo>0.8.6</version.openpojo>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>nl.jqno.equalsverifier</groupId>
+            <artifactId>equalsverifier</artifactId>
+            <version>${version.equalsverifier}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.openpojo</groupId>
+            <artifactId>openpojo</artifactId>
+            <version>${version.openpojo}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/cache/provider/AbstractCacheServiceProvider.java b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/cache/provider/AbstractCacheServiceProvider.java
new file mode 100755 (executable)
index 0000000..6a10197
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.simulator.cache.provider;
+
+import java.util.concurrent.ConcurrentHashMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@ericsson.com)
+ */
+public abstract class AbstractCacheServiceProvider {
+
+    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+    private final CacheManager cacheManager;
+
+    public AbstractCacheServiceProvider(final CacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
+
+    protected void clearCache(final String name) {
+        final Cache cache = cacheManager.getCache(name);
+        if (cache != null) {
+            final ConcurrentHashMap<?, ?> nativeCache = (ConcurrentHashMap<?, ?>) cache.getNativeCache();
+            LOGGER.info("Clear all entries from cahce: {}", cache.getName());
+            nativeCache.clear();
+        }
+    }
+
+    protected Cache getCache(final String name) {
+        return cacheManager.getCache(name);
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/configuration/SimulatorSecurityConfigurer.java b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/configuration/SimulatorSecurityConfigurer.java
new file mode 100755 (executable)
index 0000000..5d59cbb
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.simulator.configuration;
+
+import java.util.List;
+import org.onap.so.simulator.model.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+/**
+ * @author waqas.ikram@ericsson.com
+ *
+ */
+public abstract class SimulatorSecurityConfigurer extends WebSecurityConfigurerAdapter {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorSecurityConfigurer.class);
+
+
+    private final List<User> users;
+
+    public SimulatorSecurityConfigurer(final List<User> users) {
+        this.users = users;
+    }
+
+    @Bean
+    public BCryptPasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Autowired
+    public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
+        final InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication =
+                auth.inMemoryAuthentication().passwordEncoder(passwordEncoder());
+        for (int index = 0; index < users.size(); index++) {
+            final User user = users.get(index);
+            LOGGER.info("Adding {} to InMemoryUserDetailsManager ...", user);
+            inMemoryAuthentication.withUser(user.getUsername()).password(user.getPassword()).roles(user.getRole());
+            if (index < users.size()) {
+                inMemoryAuthentication.and();
+            }
+        }
+    }
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/model/User.java b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/model/User.java
new file mode 100755 (executable)
index 0000000..48d5622
--- /dev/null
@@ -0,0 +1,101 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.simulator.model;
+
+import static org.springframework.util.ObjectUtils.nullSafeEquals;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class User {
+    private String username;
+    private String password;
+    private String role;
+
+    /**
+     * @return the username
+     */
+    public String getUsername() {
+        return username;
+    }
+
+    /**
+     * @param username the username to set
+     */
+    public void setUsername(final String username) {
+        this.username = username;
+    }
+
+    /**
+     * @return the password
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * @param password the password to set
+     */
+    public void setPassword(final String password) {
+        this.password = password;
+    }
+
+    /**
+     * @return the role
+     */
+    public String getRole() {
+        return role;
+    }
+
+    /**
+     * @param role the role to set
+     */
+    public void setRole(final String role) {
+        this.role = role;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((password == null) ? 0 : password.hashCode());
+        result = prime * result + ((role == null) ? 0 : role.hashCode());
+        result = prime * result + ((username == null) ? 0 : username.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof User) {
+            final User other = (User) obj;
+            return nullSafeEquals(this.username, other.username) && nullSafeEquals(this.password, other.password)
+                    && nullSafeEquals(this.role, other.role);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "UserCredential [username=" + username + ", password=" + password + ", role=" + role + "]";
+    }
+
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/model/UserCredentials.java b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/model/UserCredentials.java
new file mode 100755 (executable)
index 0000000..f12c247
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.simulator.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Component
+@ConfigurationProperties(prefix = "spring.security")
+public class UserCredentials {
+
+    private final List<User> users = new ArrayList<>();
+
+    public List<User> getUsers() {
+        return users;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((users == null) ? 0 : users.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+
+        if (obj instanceof UserCredentials) {
+            final UserCredentials other = (UserCredentials) obj;
+            return ObjectUtils.nullSafeEquals(users, other.users);
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "UserCredentials [userCredentials=" + users + "]";
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/test/java/org/onap/so/simulator/model/PojoClassesTest.java b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/test/java/org/onap/so/simulator/model/PojoClassesTest.java
new file mode 100755 (executable)
index 0000000..8ae9b8b
--- /dev/null
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.simulator.model;
+
+import org.junit.Test;
+import org.onap.so.simulator.model.UserCredentials;
+import com.openpojo.reflection.impl.PojoClassFactory;
+import com.openpojo.validation.Validator;
+import com.openpojo.validation.ValidatorBuilder;
+import com.openpojo.validation.test.impl.GetterTester;
+import com.openpojo.validation.test.impl.SetterTester;
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
+
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class PojoClassesTest {
+
+    @Test
+    public void test_UserCredentials_class() throws ClassNotFoundException {
+        verify(UserCredentials.class);
+        validate(UserCredentials.class);
+    }
+
+    @Test
+    public void test_User_class() throws ClassNotFoundException {
+        verify(User.class);
+        validate(User.class);
+    }
+
+    private void validate(final Class<?> clazz) {
+        final Validator validator = ValidatorBuilder.create().with(new SetterTester()).with(new GetterTester()).build();
+        validator.validate(PojoClassFactory.getPojoClass(clazz));
+    }
+
+    private void verify(final Class<?> clazz) {
+        EqualsVerifier.forClass(clazz).suppress(Warning.STRICT_INHERITANCE, Warning.NONFINAL_FIELDS).verify();
+    }
+
+}
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/pom.xml b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/pom.xml
new file mode 100755 (executable)
index 0000000..b3d617d
--- /dev/null
@@ -0,0 +1,95 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>package</artifactId>
+        <groupId>org.onap.so.simulators</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>docker</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <build>
+        <finalName>${project.artifactId}-${project.version}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>io.fabric8</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>0.28.0</version>
+                <configuration>
+                    <verbose>true</verbose>
+                    <apiVersion>1.23</apiVersion>
+                    <pullRegistry>${docker.pull.registry}</pullRegistry>
+                    <pushRegistry>${docker.push.registry}</pushRegistry>
+                    <images>
+                        <image>
+                            <name>jobs/workaround-job-container</name>
+                            <build>
+                                <cleanup>try</cleanup>
+                                <dockerFileDir>docker-files</dockerFileDir>
+                                <dockerFile>Dockerfile.workaround-job-container</dockerFile>
+                            </build>
+                        </image>
+                        <image>
+                            <name>simulators/aai-simulator</name>
+                            <build>
+                                <cleanup>try</cleanup>
+                                <dockerFileDir>docker-files</dockerFileDir>
+                                <dockerFile>Dockerfile.so-simulator-base-image</dockerFile>
+                                <tags>
+                                    <tag>${project.version}</tag>
+                                </tags>
+                                <assembly>
+                                    <inline>
+                                        <dependencySets>
+                                            <dependencySet>
+                                                <includes>
+                                                    <include>${project.parent.groupId}:aai-simulator</include>
+                                                </includes>
+                                                <outputFileNameMapping>app.jar</outputFileNameMapping>
+                                            </dependencySet>
+                                        </dependencySets>
+                                    </inline>
+                                </assembly>
+                            </build>
+                        </image>
+                    </images>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>clean-images</id>
+                        <phase>pre-clean</phase>
+                        <goals>
+                            <goal>remove</goal>
+                        </goals>
+                        <configuration>
+                            <removeAll>true</removeAll>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>generate-images</id>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>build</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <version>2.8</version>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>${project.parent.groupId}</groupId>
+            <artifactId>aai-simulator</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/Dockerfile.so-simulator-base-image b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/Dockerfile.so-simulator-base-image
new file mode 100755 (executable)
index 0000000..efd7833
--- /dev/null
@@ -0,0 +1,34 @@
+FROM docker.io/openjdk:8-jdk-alpine
+
+ARG http_proxy
+ARG https_proxy
+ENV HTTP_PROXY=$http_proxy
+ENV HTTPS_PROXY=$https_proxy
+ENV http_proxy=$HTTP_PROXY
+ENV https_proxy=$HTTPS_PROXY
+
+# Update the package list and upgrade installed packages
+RUN apk update && apk upgrade
+
+# Install commonly needed tools
+RUN apk --no-cache add curl netcat-openbsd sudo nss
+
+# Create 'so' user
+RUN addgroup -g 1000 so && adduser -S -u 1000 -G so -s /bin/sh so
+
+RUN mkdir /app && mkdir /app/config  && mkdir /app/logs && mkdir /app/ca-certificates
+
+COPY maven/app.jar /app
+COPY configs/logging/logback-spring.xml /app
+COPY scripts/start-app.sh /app
+
+RUN chown -R so:so /app && chmod 700 /app/*.sh
+
+# Springboot configuration (required)
+VOLUME /app/config
+
+#  CA certificates 
+VOLUME /app/ca-certificates
+
+WORKDIR /app
+CMD ["/app/start-app.sh"]
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/Dockerfile.workaround-job-container b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/Dockerfile.workaround-job-container
new file mode 100755 (executable)
index 0000000..faf8492
--- /dev/null
@@ -0,0 +1,27 @@
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 Nordix Foundation.
+# ================================================================================
+# 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.
+# 
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# @author Waqas Ikram (waqas.ikram@est.tech)
+
+FROM docker.io/alpine
+
+# Install packages
+RUN apk update && apk upgrade && apk add mysql-client && apk add bash
+
+RUN apk --no-cache add curl netcat-openbsd sudo nss
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/configs/logging/logback-spring.xml b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/configs/logging/logback-spring.xml
new file mode 100755 (executable)
index 0000000..13c9187
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+       <property name="LOGS" value="./logs" />
+
+       <appender name="Console"
+                         class="ch.qos.logback.core.ConsoleAppender">
+               <layout class="ch.qos.logback.classic.PatternLayout">
+                       <Pattern>
+                               %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable
+                       </Pattern>
+               </layout>
+       </appender>
+
+       <appender name="RollingFile"
+                         class="ch.qos.logback.core.rolling.RollingFileAppender">
+               <file>${logs_dir:-.}/spring-boot-logger.log</file>
+               <encoder
+                               class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+                       <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+               </encoder>
+
+               <rollingPolicy
+                               class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+                       <!-- rollover daily and when the file reaches 10 MegaBytes -->
+                       <fileNamePattern>${logs_dir:-.}/archived/spring-boot-logger-%d{yyyy-MM-dd}.%i.log
+                       </fileNamePattern>
+                       <timeBasedFileNamingAndTriggeringPolicy
+                                       class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                               <maxFileSize>10MB</maxFileSize>
+                       </timeBasedFileNamingAndTriggeringPolicy>
+               </rollingPolicy>
+       </appender>
+
+       <!-- LOG everything at INFO level -->
+       <root level="info">
+               <appender-ref ref="RollingFile" />
+               <appender-ref ref="Console" />
+       </root>
+
+       <logger name="org.onap" level="trace" additivity="false">
+               <appender-ref ref="RollingFile" />
+               <appender-ref ref="Console" />
+       </logger>
+
+</configuration>
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/scripts/start-app.sh b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/scripts/start-app.sh
new file mode 100755 (executable)
index 0000000..eb8ee2e
--- /dev/null
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# ============LICENSE_START=======================================================
+#   Copyright (C) 2019 Nordix Foundation.
+# ================================================================================
+#  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.
+#
+#  SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+# @author Waqas Ikram (waqas.ikram@est.tech)
+
+touch /app/app.jar
+
+if [ "$(ls -1 /app/ca-certificates)" ]; then
+ needUpdate=FALSE
+ for certificate in `ls -1 /app/ca-certificates`; do
+    echo "Installing $certificate in /usr/local/share/ca-certificates"
+    cp /app/ca-certificates/$certificate /usr/local/share/ca-certificates/$certificate
+    needUpdate=TRUE
+ done
+ if [ $needUpdate = TRUE ]; then
+    echo "Updating ca-certificates . . ."
+    update-ca-certificates --fresh
+ fi
+fi 
+
+if [ -z "$APP" ]; then
+    echo "CONFIG ERROR: APP environment variable not set"
+    exit 1
+fi
+
+echo "Starting $APP simulator ... "
+
+if [ -z "${CONFIG_PATH}" ]; then
+    export CONFIG_PATH=/app/config/override.yaml
+fi
+
+if [ -z "${LOG_PATH}" ]; then
+    export LOG_PATH="logs/${APP}"
+fi
+
+if [ "${SSL_DEBUG}" = "log" ]; then
+    export SSL_DEBUG="-Djavax.net.debug=all"
+else
+    export SSL_DEBUG=
+fi
+
+
+jvmargs="${JVM_ARGS} -Dlogs_dir=${LOG_PATH} -Dlogging.config=/app/logback-spring.xml -Dspring.config.additional-location=$CONFIG_PATH ${SSL_DEBUG} ${DISABLE_SNI}"
+
+echo "JVM Arguments: ${jvmargs}"
+
+java ${jvmargs} -jar app.jar
+rc=$?
+
+echo "Application exiting with status code $rc"
+
+exit $rc
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/package/pom.xml b/plans/usecases/pnf-sw-upgrade/so/simulator/package/pom.xml
new file mode 100755 (executable)
index 0000000..05c9741
--- /dev/null
@@ -0,0 +1,18 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>simulator</artifactId>
+        <groupId>org.onap.so.simulators</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>package</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <modules>
+        <module>docker</module>
+    </modules>
+
+
+</project>
diff --git a/plans/usecases/pnf-sw-upgrade/so/simulator/pom.xml b/plans/usecases/pnf-sw-upgrade/so/simulator/pom.xml
new file mode 100755 (executable)
index 0000000..0cd467b
--- /dev/null
@@ -0,0 +1,84 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.onap.so.simulators</groupId>
+    <artifactId>simulator</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <version>1.0-SNAPSHOT</version>
+    <properties>
+        <jax.ws.rs>2.1</jax.ws.rs>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <jaxb.version>2.3.0</jaxb.version>
+        <javax.version>1.1.1</javax.version>
+        <java.version>1.8</java.version>
+    </properties>
+    <modules>
+        <module>common</module>
+        <module>aai-simulator</module>
+        <module>package</module>
+    </modules>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-parent</artifactId>
+                <version>2.1.5.RELEASE</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>javax.xml.bind</groupId>
+                <artifactId>jaxb-api</artifactId>
+                <version>${jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.sun.xml.bind</groupId>
+                <artifactId>jaxb-core</artifactId>
+                <version>${jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.sun.xml.bind</groupId>
+                <artifactId>jaxb-impl</artifactId>
+                <version>${jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>javax.activation</groupId>
+                <artifactId>activation</artifactId>
+                <version>${javax.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-tomcat</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+            <version>${jax.ws.rs}</version>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/so/so_setup.sh b/plans/usecases/pnf-sw-upgrade/so/so_setup.sh
new file mode 100755 (executable)
index 0000000..8c94452
--- /dev/null
@@ -0,0 +1,196 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+#   Copyright (C) 2020 Nordix Foundation.
+# ================================================================================
+#  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.
+#
+#  SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+# @author Waqas Ikram (waqas.ikram@est.tech)
+
+MAVEN_VERSION_DIR="apache-maven-3.3.9"
+MAVEN_TAR_FILE="$MAVEN_VERSION_DIR-bin.tar.gz"
+MAVEN_TAR_LOCATION="https://archive.apache.org/dist/maven/maven-3/3.3.9/binaries/$MAVEN_TAR_FILE"
+
+SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+SCRIPT_NAME=$(basename $0)
+CONFIG_DIR=$SCRIPT_HOME/config
+ENV_FILE=$CONFIG_DIR/env
+TEMP_DIR_PATH=$SCRIPT_HOME/temp
+TEST_LAB_DIR_PATH=$TEMP_DIR_PATH/test_lab
+DOCKER_COMPOSE_FILE_PATH=$SCRIPT_HOME/docker-compose.yml
+DOCKER_COMPOSE_LOCAL_OVERRIDE_FILE=$SCRIPT_HOME/docker-compose.local.yml
+TEAR_DOWN_SCRIPT=$SCRIPT_HOME/teardown.sh
+
+MAVEN_DIR=$TEMP_DIR_PATH/maven
+INSTALLED_MAVEN_DIR=$MAVEN_DIR/$MAVEN_VERSION_DIR
+MVN=$INSTALLED_MAVEN_DIR/bin/mvn
+MVN_VERSION="$MVN -v"
+MVN_SETTINGS_XML="$SCRIPT_HOME/settings.xml"
+MVN_CLEAN_INSTALL="$MVN clean install"
+SIMULATOR_MAVEN_PROJECT_POM="$SCRIPT_HOME/simulator/pom.xml"
+WAIT_FOR_WORKAROUND_SCRIPT=$CONFIG_DIR/"wait-for-workaround-job.sh"
+WAIT_FOR_POPULATE_AAI_SCRIPT=$CONFIG_DIR/"wait-for-aai-config-job.sh"
+WAIT_FOR_CONTAINER_SCRIPT=$CONFIG_DIR/"wait-for-container.sh"
+PNF_PAYLOAD_PATH=$CONFIG_DIR/aai-simulator-populate-data/pnf.json
+
+echo "Running $SCRIPT_HOME/$SCRIPT_NAME ..."
+
+export $(egrep -v '^#' $ENV_FILE | xargs)
+
+MANDATORY_VARIABLES_NAMES=( "NEXUS_DOCKER_REPO_MSO" "DOCKER_ENVIRONMENT" "TAG" "TIME_OUT_DEFAULT_VALUE_SEC" "PROJECT_NAME" "DEFAULT_NETWORK_NAME")
+
+for var in "${MANDATORY_VARIABLES_NAMES[@]}"
+ do
+   if [ -z "${!var}" ]; then
+     echo "Missing mandatory attribute $var in $ENV_FILE"
+     exit 1
+  fi
+done
+
+if [[ ! "$TEMP_DIR_PATH" || ! -d "$TEMP_DIR_PATH" ]]; then
+        echo "Creating temporary directory $TEMP_DIR_PATH"
+        mkdir $TEMP_DIR_PATH
+
+        if [ $? -ne 0 ]; then
+                echo "Could not create $TEMP_DIR_PATH"
+                exit 1
+        fi
+
+fi
+echo "Will use ${TEMP_DIR_PATH} directory"
+
+if [[ ! "$MAVEN_DIR" || ! -d "$MAVEN_DIR" ]]; then
+        echo "Creating temporary maven directory $MAVEN_DIR"
+        mkdir $MAVEN_DIR
+
+        if [ $? -ne 0 ]; then
+                echo "Could not create $MAVEN_DIR"
+                exit 1
+        fi
+fi
+echo "Will use ${MAVEN_DIR} directory for maven install"
+
+if [[ ! "$INSTALLED_MAVEN_DIR" || ! -d "$INSTALLED_MAVEN_DIR" ]]; then
+        echo "Installing maven ..."
+        cd $MAVEN_DIR
+
+        CURL=`which curl`
+        if [[ ! "$CURL" ]]; then
+                echo "curl command is not installed"
+                echo "Unable to execute test plan"
+                exit 1
+        fi
+        curl -O $MAVEN_TAR_LOCATION
+
+        TAR=`which tar`
+        if [[ ! "$TAR" ]]; then
+                echo "tar command is not installed"
+                echo "Unable to execute test plan"
+                exit 1
+        fi
+
+        tar -xzvf $MAVEN_TAR_FILE
+
+        echo "Finished installing maven ..."
+fi
+
+echo "Maven installed under directory $INSTALLED_MAVEN_DIR"
+
+$MVN_VERSION
+
+if [ $? -ne 0 ]; then
+        echo "Unable to run mvn -v command"
+        exit 1
+fi
+
+cd $SCRIPT_HOME
+
+echo "Will build simulator project using $MVN_CLEAN_INSTALL -f $SIMULATOR_MAVEN_PROJECT_POM --settings $MVN_SETTINGS_XML"
+$MVN_CLEAN_INSTALL -f $SIMULATOR_MAVEN_PROJECT_POM --settings $MVN_SETTINGS_XML
+
+if [ $? -ne 0 ]; then
+        echo "Maven build failed"
+         exit 1
+fi
+
+echo "Will clone docker-config project ... "
+
+
+if [[ -d "$TEST_LAB_DIR_PATH" ]]; then
+       echo "$TEST_LAB_DIR_PATH already exists"
+       echo "Removing $TEST_LAB_DIR_PATH directory ..."
+       rm -rf $TEST_LAB_DIR_PATH
+fi
+
+git clone http://gerrit.onap.org/r/so/docker-config.git $TEST_LAB_DIR_PATH
+
+export TEST_LAB_DIR=$TEST_LAB_DIR_PATH
+export CONFIG_DIR_PATH=$CONFIG_DIR
+
+if [ "$DOCKER_ENVIRONMENT" == "remote" ]; then
+  echo "Starting docker containers with remote images ..."
+  docker-compose -f $DOCKER_COMPOSE_FILE_PATH -p $PROJECT_NAME up -d mariadb
+  sleep 1m
+  docker-compose -f $DOCKER_COMPOSE_FILE_PATH -p $PROJECT_NAME up -d
+elif [ "$DOCKER_ENVIRONMENT" == "local" ]; then
+  echo "Starting docker containers with local images ..."
+  docker-compose -f $DOCKER_COMPOSE_FILE_PATH -f $DOCKER_COMPOSE_LOCAL_OVERRIDE_FILE -p $PROJECT_NAME up -d mariadb
+  sleep 1m
+  docker-compose -f $DOCKER_COMPOSE_FILE_PATH -f $DOCKER_COMPOSE_LOCAL_OVERRIDE_FILE -p $PROJECT_NAME up -d
+else
+  echo "DOCKER_ENVIRONMENT not set correctly in $ENV_FILE.  Allowed values: local | remote"
+  exit 1
+fi
+
+echo "Sleeping for 2m"
+sleep 2m
+
+echo "updating PNF ip-address in pnf.json"
+sed -i "s/pnfaddr/$LOCAL_IP/g" $PNF_PAYLOAD_PATH
+
+echo "Will execute $WAIT_FOR_WORKAROUND_SCRIPT script"
+$WAIT_FOR_WORKAROUND_SCRIPT
+
+if [ $? -ne 0 ]; then
+   echo "ERROR: $WAIT_FOR_WORKAROUND_SCRIPT failed"
+   echo "Will stop running docker containers . . ."
+   $TEAR_DOWN_SCRIPT
+   exit 1
+fi
+
+
+echo "Will execute $WAIT_FOR_POPULATE_AAI_SCRIPT script"
+$WAIT_FOR_POPULATE_AAI_SCRIPT
+
+if [ $? -ne 0 ]; then
+   echo "ERROR: $WAIT_FOR_POPULATE_AAI_SCRIPT failed"
+   echo "Will stop running docker containers . . ."
+   $TEAR_DOWN_SCRIPT
+   exit 1
+fi
+
+API_INFRA_CONTAINER_NAME="api-handler-infra"
+echo "Will execute $WAIT_FOR_CONTAINER_SCRIPT to wait for $API_INFRA_CONTAINER_NAME container to start up"
+$WAIT_FOR_CONTAINER_SCRIPT -c "$API_INFRA_CONTAINER_NAME" -t "300" -n "$DEFAULT_NETWORK_NAME"
+
+if [ $? -ne 0 ]; then
+   echo "ERROR: $WAIT_FOR_CONTAINER_SCRIPT failed"
+   echo "Will stop running docker containers . . ."
+   $TEAR_DOWN_SCRIPT
+   exit 1
+fi
+
+echo "Finished executing $SCRIPT_HOME/$SCRIPT_NAME"
diff --git a/plans/usecases/pnf-sw-upgrade/so/so_teardown.sh b/plans/usecases/pnf-sw-upgrade/so/so_teardown.sh
new file mode 100755 (executable)
index 0000000..e2fbdb7
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+SCRIPT_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+SCRIPT_NAME=$(basename $0)
+CONFIG_DIR=$SCRIPT_HOME/config
+ENV_FILE=$CONFIG_DIR/env
+TEMP_DIR_PATH=$SCRIPT_HOME/temp
+TEST_LAB_DIR_PATH=$TEMP_DIR_PATH/test_lab
+DOCKER_COMPOSE_FILE_PATH=$SCRIPT_HOME/docker-compose.yml
+DOCKER_COMPOSE_LOCAL_OVERRIDE_FILE=$SCRIPT_HOME/docker-compose.local.yml
+
+echo "Running $SCRIPT_HOME/$SCRIPT_NAME ..."
+export $(egrep -v '^#' $ENV_FILE | xargs)
+export TEST_LAB_DIR=$TEST_LAB_DIR_PATH
+export CONFIG_DIR_PATH=$CONFIG_DIR
+
+if [ "$DOCKER_ENVIRONMENT" == "remote" ]; then
+  echo "Tearing down docker containers from remote images ..."
+  docker-compose -f $DOCKER_COMPOSE_FILE_PATH -p $PROJECT_NAME down
+elif [ "$DOCKER_ENVIRONMENT" == "local" ]; then
+  echo "Tearing down docker containers from local images ..."
+  docker-compose -f $DOCKER_COMPOSE_FILE_PATH -f $DOCKER_COMPOSE_LOCAL_OVERRIDE_FILE -p $PROJECT_NAME down
+else
+  echo "Couldn't find valid property for DOCKER_ENVIRONMENT in $ENV_FILE."
+  echo "Attempting normal teardown ..."
+  docker-compose -f $DOCKER_COMPOSE_FILE_PATH -p $PROJECT_NAME down
+fi
+
+echo "Finished executing $SCRIPT_HOME/$SCRIPT_NAME"
diff --git a/plans/usecases/pnf-sw-upgrade/teardown.sh b/plans/usecases/pnf-sw-upgrade/teardown.sh
new file mode 100755 (executable)
index 0000000..a9d9bdd
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+source $SO_DOCKER_PATH/so_teardown.sh
+
+source $SDNC_DOCKER_PATH/sdn_teardown.sh
+
+source $CDS_DOCKER_PATH/cds_teardown.sh
+
+PNFSIM_DOCKER_COMPOSE_PATH=$PNF_SIM_DOCKER_PATH/docker-compose.yml
+docker-compose -f $PNFSIM_DOCKER_COMPOSE_PATH -p $PROJECT_NAME down
diff --git a/plans/usecases/pnf-sw-upgrade/test.properties b/plans/usecases/pnf-sw-upgrade/test.properties
new file mode 100644 (file)
index 0000000..23b45d3
--- /dev/null
@@ -0,0 +1,17 @@
+NEXUS_DOCKER_REPO=nexus3.onap.org:10001
+NEXUS_USERNAME=docker
+NEXUS_PASSWD=docker
+REQUEST_DATA_PATH=$WORKSPACE/tests/$PARENT/$SUB_PARENT/data
+TC_PLANS_PATH=$WORKSPACE/plans/$PARENT/$SUB_PARENT
+CDS_DOCKER_PATH=$TC_PLANS_PATH/cds
+CDS_CERT_PATH=$CDS_DOCKER_PATH/cert
+SDNC_DOCKER_PATH=$TC_PLANS_PATH/sdn
+PNF_SIM_DOCKER_PATH=$TC_PLANS_PATH/simulators/pnfsim
+CERT_SUBPATH=$SDNC_DOCKER_PATH/certs
+APP_CONFIG_HOME=/opt/app/onap/config
+SO_DOCKER_PATH=$TC_PLANS_PATH/so
+PROJECT_NAME=pnfSwU
+
+SDNC_IMAGE_TAG=1.8.0-STAGING-latest
+BP_IMAGE_TAG=0.7.0-STAGING-latest
+NETOPEER_IMAGE_TAG=v2.5.0
\ No newline at end of file
diff --git a/plans/usecases/pnf-sw-upgrade/testplan.txt b/plans/usecases/pnf-sw-upgrade/testplan.txt
new file mode 100644 (file)
index 0000000..61a3139
--- /dev/null
@@ -0,0 +1,4 @@
+# Test suites are relative paths under [integration/csit.git]/tests/.
+# Place the suites in run order.
+usecases/pnf-sw-upgrade
+
index 2c45812..634b0c7 100755 (executable)
 # functions
 #
 
+function on_exit(){
+    rc=$?
+    rsync -av "$WORKDIR/" "$WORKSPACE/archives"
+
+    # Record list of active docker containers
+    docker ps --format "{{.Image}}" > "$WORKSPACE/archives/_docker-images.log"
+
+    # show memory consumption after all docker instances initialized
+    docker_stats | tee "$WORKSPACE/archives/_sysinfo-2-after-robot.txt"
+
+    # Run teardown script plan if it exists
+    cd "${TESTPLANDIR}"
+    TEARDOWN="${TESTPLANDIR}/teardown.sh"
+    if [ -f "${TEARDOWN}" ]; then
+        echo "Running teardown script ${TEARDOWN}"
+        source_safely "${TEARDOWN}"
+    fi
+    # TODO: do something with the output
+     exit $rc
+}
+# ensure that teardown and other finalizing steps are always executed
+trap on_exit EXIT
+
 function docker_stats(){
     #General memory details
     echo "> top -bn1 | head -3"
@@ -166,22 +189,5 @@ python -m robot.run -N ${TESTPLAN} -v WORKSPACE:/tmp ${ROBOT_VARIABLES} ${TESTOP
 RESULT=$?
 load_set
 echo "RESULT: $RESULT"
-rsync -av "$WORKDIR/" "$WORKSPACE/archives"
-
-# Record list of active docker containers
-docker ps --format "{{.Image}}" > "$WORKSPACE/archives/_docker-images.log"
-
-# show memory consumption after all docker instances initialized
-docker_stats | tee "$WORKSPACE/archives/_sysinfo-2-after-robot.txt"
-
-# Run teardown script plan if it exists
-cd "${TESTPLANDIR}"
-TEARDOWN="${TESTPLANDIR}/teardown.sh"
-if [ -f "${TEARDOWN}" ]; then
-    echo "Running teardown script ${TEARDOWN}"
-    source_safely "${TEARDOWN}"
-fi
-
-# TODO: do something with the output
-
+# Note that the final steps are done in on_exit function after this exit!
 exit $RESULT
index 55f557c..8df0d07 100644 (file)
@@ -131,6 +131,9 @@ log_dir = /var/log
 #fatal_deprecations = false
 
 
+[auth]
+appkey = h@ss3crtky400fdntc#001
+
 [aaf_api]
 
 #
index 9aa7606..862691f 100755 (executable)
@@ -72,9 +72,9 @@ sed  -i -e "s%localhost:8100/%${AAFSIM_IP}:8100/%g" /tmp/conductor/properties/co
 #SMS
 sed  -i -e "s%aaf-sms.onap:10443%${SMS_IP}:10443%g" /tmp/conductor/properties/conductor.conf
 #Preload secrets
-docker exec -i sms /bin/sh -c "mkdir -p /preload/config"
+docker exec --user root -i sms /bin/sh -c "mkdir -p /preload/config"
 docker cp /tmp/sms/properties/has.json sms:/preload/config/has.json
-docker exec -i sms /bin/sh -c "/sms/bin/preload -cacert /sms/certs/aaf_root_ca.cer -jsondir /preload/config -serviceport 10443 -serviceurl http://localhost"
+docker exec --user root -i sms /bin/sh -c "/sms/bin/preload -cacert /sms/certs/aaf_root_ca.cer -jsondir /preload/config -serviceport 10443 -serviceurl http://localhost"
 docker logs vault
 
 #onboard conductor into music
diff --git a/scripts/optf-has/has/setup-sms.sh b/scripts/optf-has/has/setup-sms.sh
new file mode 100755 (executable)
index 0000000..e6a4b22
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# Copyright 2018 Intel Corporation
+#
+# 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.
+#
+
+# Not sure why this is needed.
+source ${SCRIPTS}/common_functions.sh
+
+CONFIG_FILE=$(pwd)/config/smsconfig.json
+
+mkdir -p $(pwd)/config
+
+docker login -u docker -p docker nexus3.onap.org:10001
+docker pull nexus3.onap.org:10001/onap/aaf/sms
+docker pull docker.io/vault:1.3.3
+
+#
+# Running vault in dev server mode here for CSIT
+# In HELM it runs in production mode
+#
+docker run -e "VAULT_DEV_ROOT_TOKEN_ID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" \
+           -e SKIP_SETCAP=true \
+           --name vault -d -p 8200:8200 vault:1.3.3
+
+SMSDB_IP=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' vault)
+cat << EOF > $CONFIG_FILE
+{
+    "cafile": "auth/selfsignedca.pem",
+    "servercert": "auth/server.cert",
+    "serverkey":  "auth/server.key",
+
+    "smsdbaddress":     "http://$SMSDB_IP:8200",
+    "vaulttoken":       "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
+    "disable_tls": true
+}
+EOF
+
+cat $CONFIG_FILE
+
+docker run --workdir /sms -v $CONFIG_FILE:/sms/smsconfig.json \
+           --name sms -d -p 10443:10443 --user root nexus3.onap.org:10001/onap/aaf/sms
+
+SMS_IP=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' sms)
+
+echo "###### WAITING FOR ALL CONTAINERS TO COME UP"
+sleep 20
+for i in {1..20}; do
+    curl -sS -m 1 http://${SMSDB_IP}:8200/v1/sys/seal-status && break
+    echo sleep $i
+    sleep $i
+done
+
+#
+# add here all ROBOT_VARIABLES settings
+#
+echo "# sms robot variables settings";
+ROBOT_VARIABLES="-v SMS_HOSTNAME:http://${SMS_IP} -v SMS_PORT:10443"
+
+echo ${ROBOT_VARIABLES}
index 0950957..e52cb0c 100644 (file)
                 "name": "conductor",
                 "values": {
                     "UserName": "admin1",
-                    "Password": "plan.15"
+                    "Password": "22234d3472ef5da8ecba5a096110a024f1db5cf195c665f910d558c9e83db19d"
                 }
             },
             {
                 "name": "policyPlatform",
                 "values": {
                     "UserName": "testpdp",
-                    "Password": "alpha123"
+                    "Password": "7a03bdee7a0381daf4ee426b9d2b695e3f4233ffd19a852a3fb0ff0156fbdde7"
                 }
             },
             {
                 "name": "policyClient",
                 "values": {
                     "UserName": "python",
-                    "Password": "test"
+                    "Password": "3a3c8546c91f99f4becc069ba0fbb13ef46f4f3028f5bba09f3f4a9030ddc0a0"
                 }
             },
             {
                 "name": "osdfPlacement",
                 "values": {
                     "UserName": "test",
-                    "Password": "testpwd"
+                    "Password": "c66b1570ae257375e500f9fe0e62b2a325466137ac5f29581e2e05cce1170212"
                 }
             },
             {
                 "name": "osdfPlacementSO",
                 "values": {
                     "UserName": "so_test",
-                    "Password": "so_testpwd"
+                    "Password": "3d62d49b3e4ada38fd4146d2d82f4ba2f09345a46f15970cd439924c991b8202"
                 }
             },
             {
                 "name": "osdfPlacementVFC",
                 "values": {
                     "UserName": "vfc_test",
-                    "Password": "vfc_testpwd"
+                    "Password": "1fb1cd581f96060d29ecad06be97151656bf29bce66bad587cd2fbaf5ea1e66d"
                 }
             },
             {
                 "name": "osdfCMScheduler",
                 "values": {
                     "UserName": "test1",
-                    "Password": "testpwd1"
+                    "Password": "c5279fb02d7bac5269b1a644ac8e36f41f6ba7a2eae03dc469cb80d71811322b"
                 }
             },
             {
                 "name": "configDb",
                 "values": {
                     "UserName": "osdf",
-                    "Password": "passwd"
+                    "Password": "40697f254409c2b97763892ecdeb50c847d605f5beb6f988f1c142a7e0344d0c"
                 }
             },
             {
                 "name": "osdfPCIOpt",
                 "values": {
                     "UserName": "pci_test",
-                    "Password": "pci_testpwd"
+                    "Password": "fbf4dcb7f7cda8fdfb742838b0c90ae5bea249801f3f725fdc98941a6e4c347c"
+                }
+            },
+            {
+                "name": "osdfOptEngine",
+                "values": {
+                    "UserName": "opt_test",
+                    "Password": "02946408ce6353d45540cd01d912686f19f48c3d8a955d5effdc14c6a43477e5"
                 }
             }
         ]
index f8f7500..6578567 100755 (executable)
@@ -18,7 +18,7 @@ conductorMaxRetries: 5  # if we don't get something in 30 minutes, give up
 conductorMinorVersion: 0
 
 # Policy Platform -- requires ClientAuth, Authorization, and Environment
-policyPlatformUrl: http://127.0.0.1:5000/simulated/policy/pdp-has-vcpe-good/getConfig # Policy Dev platform URL
+policyPlatformUrl: http://127.0.0.1:5000/simulated/policy/pdpx/decision/v1 # Policy Dev platform URL
 policyPlatformEnv: TEST  # Environment for policy platform
 
 # Config for DMaaP
@@ -47,3 +47,6 @@ aaf_ca_certs: ssl_certs/aaf_root_ca.cer
 configDbUrl: http://127.0.0.1:5000/simulated/configdb
 configDbGetCellListUrl: 'getCellList'
 configDbGetNbrListUrl: 'getNbrList'
+
+#key
+appkey: os35@rrtky400fdntc#001t5
\ No newline at end of file
index 6d4efa1..3554b55 100755 (executable)
@@ -34,7 +34,7 @@ cd ${DIR}
 # run docker containers
 OSDF_CONF=/tmp/osdf/properties/osdf_config.yaml
 IMAGE_NAME=nexus3.onap.org:10001/onap/optf-osdf
-IMAGE_VER=1.2.4-SNAPSHOT-latest
+IMAGE_VER=2.0.1-SNAPSHOT-latest
 
 mkdir -p /tmp/osdf/properties
 mkdir -p /tmp/sms/properties
@@ -52,9 +52,9 @@ sed  -i -e "s%127.0.0.1:5000%${OSDF_SIM_IP}:5000%g" $OSDF_CONF
 sed  -i -e "s%aaf-sms.onap:10443%${SMS_IP}:10443%g" $OSDF_CONF
 
 #Preload secrets
-docker exec -i sms /bin/sh -c "mkdir -p /preload/config"
+docker exec --user root -i sms  /bin/sh -c "mkdir -p /preload/config"
 docker cp /tmp/sms/properties/osdf.json sms:/preload/config/osdf.json
-docker exec -i sms /bin/sh -c "/sms/bin/preload -cacert /sms/certs/aaf_root_ca.cer -jsondir /preload/config -serviceport 10443 -serviceurl http://localhost"
+docker exec --user root -i sms  /bin/sh -c "/sms/bin/preload -cacert /sms/certs/aaf_root_ca.cer -jsondir /preload/config -serviceport 10443 -serviceurl http://localhost"
 
 docker logs vault
 docker run -d --name optf-osdf -v ${OSDF_CONF}:/opt/osdf/config/osdf_config.yaml -p "8698:8699" ${IMAGE_NAME}:${IMAGE_VER}
diff --git a/scripts/optf-osdf/osdf/setup-sms.sh b/scripts/optf-osdf/osdf/setup-sms.sh
new file mode 100755 (executable)
index 0000000..e6a4b22
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/bash
+#
+# Copyright 2018 Intel Corporation
+#
+# 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.
+#
+
+# Not sure why this is needed.
+source ${SCRIPTS}/common_functions.sh
+
+CONFIG_FILE=$(pwd)/config/smsconfig.json
+
+mkdir -p $(pwd)/config
+
+docker login -u docker -p docker nexus3.onap.org:10001
+docker pull nexus3.onap.org:10001/onap/aaf/sms
+docker pull docker.io/vault:1.3.3
+
+#
+# Running vault in dev server mode here for CSIT
+# In HELM it runs in production mode
+#
+docker run -e "VAULT_DEV_ROOT_TOKEN_ID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" \
+           -e SKIP_SETCAP=true \
+           --name vault -d -p 8200:8200 vault:1.3.3
+
+SMSDB_IP=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' vault)
+cat << EOF > $CONFIG_FILE
+{
+    "cafile": "auth/selfsignedca.pem",
+    "servercert": "auth/server.cert",
+    "serverkey":  "auth/server.key",
+
+    "smsdbaddress":     "http://$SMSDB_IP:8200",
+    "vaulttoken":       "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
+    "disable_tls": true
+}
+EOF
+
+cat $CONFIG_FILE
+
+docker run --workdir /sms -v $CONFIG_FILE:/sms/smsconfig.json \
+           --name sms -d -p 10443:10443 --user root nexus3.onap.org:10001/onap/aaf/sms
+
+SMS_IP=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' sms)
+
+echo "###### WAITING FOR ALL CONTAINERS TO COME UP"
+sleep 20
+for i in {1..20}; do
+    curl -sS -m 1 http://${SMSDB_IP}:8200/v1/sys/seal-status && break
+    echo sleep $i
+    sleep $i
+done
+
+#
+# add here all ROBOT_VARIABLES settings
+#
+echo "# sms robot variables settings";
+ROBOT_VARIABLES="-v SMS_HOSTNAME:http://${SMS_IP} -v SMS_PORT:10443"
+
+echo ${ROBOT_VARIABLES}
index 909d8f4..4b0c219 100755 (executable)
 sed -i "s/^dmaap/noop/g" \
     ${POLICY_HOME}/config/engine.properties \
     ${POLICY_HOME}/config/feature-lifecycle.properties \
-    ${POLICY_HOME}/config/frankfurt-controller.properties \
-    ${POLICY_HOME}/config/usecases-controller.properties
+    ${POLICY_HOME}/config/frankfurt-controller.properties
 
 chmod 644 ${POLICY_HOME}/config/engine.properties \
     ${POLICY_HOME}/config/feature-lifecycle.properties \
-    ${POLICY_HOME}/config/frankfurt-controller.properties \
-    ${POLICY_HOME}/config/usecases-controller.properties
+    ${POLICY_HOME}/config/frankfurt-controller.properties
index c11e7e9..b5e7cbd 100644 (file)
@@ -80,11 +80,13 @@ PAP_PASSWORD=alpha123
 
 PDP_HOST=pdp
 PDP_PORT=6969
+PDP_CONTEXT_URI=policy/pdpx/v1/
 PDP_USERNAME=testpdp
 PDP_PASSWORD=alpha123
 PDP_CLIENT_USERNAME=python
 PDP_CLIENT_PASSWORD=test
 PDP_ENVIRONMENT=TEST
+GUARD_DISABLED=false
 
 # DCAE DMaaP
 
@@ -100,7 +102,7 @@ DMAAP_SERVERS=mr.api.simpledemo.onap.org
 
 AAI_HOST=aai.api.simpledemo.onap.org
 AAI_PORT=8443
-AAI_URL=https://aai.api.simpledemo.onap.org:8443
+AAI_CONTEXT_URI=
 AAI_USERNAME=policy@policy.onap.org
 AAI_PASSWORD=demo123456!
 
@@ -108,6 +110,7 @@ AAI_PASSWORD=demo123456!
 
 SO_HOST=vm1.mso.simpledemo.onap.org
 SO_PORT=8080
+SO_CONTEXT_URI=onap/so/infra/
 SO_URL=http://vm1.mso.simpledemo.onap.org:8080/onap/so/infra
 SO_USERNAME=InfraPortalClient
 SO_PASSWORD=password1$
@@ -116,7 +119,7 @@ SO_PASSWORD=password1$
 
 VFC_HOST=
 VFC_PORT=
-VFC_URL=
+VFC_CONTEXT_URI=api/nslcm/v1/
 VFC_USERNAME=
 VFC_PASSWORD=
 
@@ -124,6 +127,6 @@ VFC_PASSWORD=
 
 SDNC_HOST=
 SDNC_PORT=
-SDNC_URL=
+SDNC_CONTEXT_URI=restconf/operations/
 SDNC_USERNAME=
 SDNC_PASSWORD=
index 8fef8a2..891de49 100644 (file)
@@ -79,11 +79,14 @@ PAP_PASSWORD=
 # PDP-X
 
 PDP_HOST=
+PDP_PORT=
+PDP_CONTEXT_URI=policy/pdpx/v1/
 PDP_USERNAME=
 PDP_PASSWORD=
 PDP_CLIENT_USERNAME=
 PDP_CLIENT_PASSWORD=
 PDP_ENVIRONMENT=
+GUARD_DISABLED=false
 
 # DCAE DMaaP
 
@@ -97,24 +100,33 @@ DMAAP_SERVERS=mr.api.simpledemo.onap.org
 
 # AAI
 
-AAI_URL=https://aai.api.simpledemo.onap.org:8443
+AAI_HOST=aai.api.simpledemo.onap.org
+AAI_PORT=8443
+AAI_CONTEXT_URI=
 AAI_USERNAME=policy@policy.onap.org
 AAI_PASSWORD=demo123456!
 
 # MSO
 
+SO_HOST=vm1.mso.simpledemo.onap.org
+SO_PORT=8080
+SO_CONTEXT_URI=onap/so/infra/
 SO_URL=http://vm1.mso.simpledemo.onap.org:8080/onap/so/infra
 SO_USERNAME=InfraPortalClient
 SO_PASSWORD=password1$
 
 # VFC
 
-VFC_URL=
+VFC_HOST=
+VFC_PORT=
+VFC_CONTEXT_URI=api/nslcm/v1/
 VFC_USERNAME=
 VFC_PASSWORD=
 
 # SDNC
 
-SDNC_URL=
+SDNC_HOST=
+SDNC_PORT=
+SDNC_CONTEXT_URI=restconf/operations/
 SDNC_USERNAME=
 SDNC_PASSWORD=
diff --git a/scripts/policy/config/pap/onap.policies.monitoring.cdap.tca.hi.lo.app.json b/scripts/policy/config/pap/onap.policies.monitoring.cdap.tca.hi.lo.app.json
deleted file mode 100644 (file)
index 0657473..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-{
-  "tosca_definitions_version": "tosca_simple_yaml_1_1_0",
-  "policy_types": {
-    "onap.policies.Monitoring": {
-      "derived_from": "tosca.policies.Root",
-      "description": "a base policy type for all policies that governs monitoring provisioning"
-    },
-    "onap.policies.monitoring.cdap.tca.hi.lo.app": {
-      "derived_from": "onap.policies.Monitoring",
-      "version": "1.0.0",
-      "properties": {
-        "tca_policy": {
-          "type": "onap.datatypes.monitoring.tca_policy",
-          "description": "TCA Policy JSON"
-        }
-      }
-    }
-  },
-  "data_types": {
-    "onap.datatypes.monitoring.metricsPerEventName": {
-      "derived_from": "tosca.datatypes.Root",
-      "properties": {
-        "controlLoopSchemaType": {
-          "type": "string",
-          "required": true,
-          "description": "Specifies Control Loop Schema Type for the event Name e.g. VNF, VM",
-          "constraints": [
-            {
-              "valid_values": [
-                "VM",
-                "VNF"
-              ]
-            }
-          ]
-        },
-        "eventName": {
-          "type": "string",
-          "required": true,
-          "description": "Event name to which thresholds need to be applied"
-        },
-        "policyName": {
-          "type": "string",
-          "required": true,
-          "description": "TCA Policy Scope Name"
-        },
-        "policyScope": {
-          "type": "string",
-          "required": true,
-          "description": "TCA Policy Scope"
-        },
-        "policyVersion": {
-          "type": "string",
-          "required": true,
-          "description": "TCA Policy Scope Version"
-        },
-        "thresholds": {
-          "type": "list",
-          "required": true,
-          "description": "Thresholds associated with eventName",
-          "entry_schema": {
-            "type": "onap.datatypes.monitoring.thresholds"
-          }
-        }
-      }
-    },
-    "onap.datatypes.monitoring.tca_policy": {
-      "derived_from": "tosca.datatypes.Root",
-      "properties": {
-        "domain": {
-          "type": "string",
-          "required": true,
-          "description": "Domain name to which TCA needs to be applied",
-          "default": "measurementsForVfScaling",
-          "constraints": [
-            {
-              "equal": "measurementsForVfScaling"
-            }
-          ]
-        },
-        "metricsPerEventName": {
-          "type": "list",
-          "required": true,
-          "description": "Contains eventName and threshold details that need to be applied to given eventName",
-          "entry_schema": {
-            "type": "onap.datatypes.monitoring.metricsPerEventName"
-          }
-        }
-      }
-    },
-    "onap.datatypes.monitoring.thresholds": {
-      "derived_from": "tosca.datatypes.Root",
-      "properties": {
-        "closedLoopControlName": {
-          "type": "string",
-          "required": true,
-          "description": "Closed Loop Control Name associated with the threshold"
-        },
-        "closedLoopEventStatus": {
-          "type": "string",
-          "required": true,
-          "description": "Closed Loop Event Status of the threshold",
-          "constraints": [
-            {
-              "valid_values": [
-                "ONSET",
-                "ABATED"
-              ]
-            }
-          ]
-        },
-        "direction": {
-          "type": "string",
-          "required": true,
-          "description": "Direction of the threshold",
-          "constraints": [
-            {
-              "valid_values": [
-                "LESS",
-                "LESS_OR_EQUAL",
-                "GREATER",
-                "GREATER_OR_EQUAL",
-                "EQUAL"
-              ]
-            }
-          ]
-        },
-        "fieldPath": {
-          "type": "string",
-          "required": true,
-          "description": "Json field Path as per CEF message which needs to be analyzed for TCA",
-          "constraints": [
-            {
-              "valid_values": [
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated",
-                "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle",
-                "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt",
-                "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice",
-                "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq",
-                "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal",
-                "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem",
-                "$.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait",
-                "$.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage",
-                "$.event.measurementsForVfScalingFields.meanRequestLatency",
-                "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered",
-                "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached",
-                "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured",
-                "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree",
-                "$.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed",
-                "$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value"
-              ]
-            }
-          ]
-        },
-        "severity": {
-          "type": "string",
-          "required": true,
-          "description": "Threshold Event Severity",
-          "constraints": [
-            {
-              "valid_values": [
-                "CRITICAL",
-                "MAJOR",
-                "MINOR",
-                "WARNING",
-                "NORMAL"
-              ]
-            }
-          ]
-        },
-        "thresholdValue": {
-          "type": "integer",
-          "required": true,
-          "description": "Threshold value for the field Path inside CEF message"
-        },
-        "version": {
-          "type": "string",
-          "required": true,
-          "description": "Version number associated with the threshold"
-        }
-      }
-    }
-  }
-}
index 1bab189..e32190f 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2019 AT&T Intellectual Property. All rights reserved
+# Copyright 2019-2020 AT&T Intellectual Property. 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.
@@ -12,9 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 version: '2'
-networks:
-  default:
-    driver: bridge
 services:
    mariadb:
       image: mariadb:${POLICY_MARIADB_VER}
@@ -24,16 +21,16 @@ services:
       env_file: config/db/db.conf
       volumes:
          - ./config/db:/docker-entrypoint-initdb.d
-      ports:
-       - "3306:3306"
+      expose:
+       - 3306
    api:
       image: nexus3.onap.org:10001/onap/policy-api:${POLICY_API_VERSION}
       container_name: policy-api
       depends_on:
        - mariadb
       hostname: policy-api
-      ports:
-       - "6969:6969"
+      expose:
+       - 6969
    start_dependencies:
       image: dadarek/wait-for-dependencies
       environment:
index 970f116..5438557 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2019 AT&T Intellectual Property. All rights reserved
+# Copyright 2019-2020 AT&T Intellectual Property. 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.
@@ -12,9 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 version: '2'
-networks:
-  default:
-    driver: bridge
 services:
    mariadb:
       image: mariadb:${POLICY_MARIADB_VER}
@@ -24,24 +21,24 @@ services:
       env_file: config/db/db.conf
       volumes:
          - ./config/db:/docker-entrypoint-initdb.d
-      ports:
-       - "3306:3306"
+      expose:
+       - 3306
    pap:
       image: nexus3.onap.org:10001/onap/policy-pap:${POLICY_PAP_VERSION}
       container_name: policy-pap
       depends_on:
        - mariadb
       hostname: policy-pap
-      ports:
-       - "6969:6969"
+      expose:
+       - 6969
    api:
       image: nexus3.onap.org:10001/onap/policy-api:${POLICY_API_VERSION}
       container_name: policy-api
       depends_on:
        - mariadb
       hostname: policy-api
-      ports:
-       - "9969:6969"
+      expose:
+       - 6969
    start_dependencies:
       image: dadarek/wait-for-dependencies
       environment:
index af1cbae..caf8315 100644 (file)
@@ -1,5 +1,5 @@
 # ============LICENSE_START=======================================================
-#  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+#  Copyright (C) 2019-2020 AT&T Intellectual Property. 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.
@@ -16,9 +16,6 @@
 # SPDX-License-Identifier: Apache-2.0
 # ============LICENSE_END=========================================================
 version: '2'
-networks:
-  default:
-    driver: bridge
 services:
    mariadb:
       image: mariadb:${POLICY_MARIADB_VER}
@@ -28,14 +25,14 @@ services:
       env_file: config/db/db.conf
       volumes:
          - ./config/db:/docker-entrypoint-initdb.d
-      ports:
-       - "3306:3306"
+      expose:
+       - 3306
    message-router:
       image: dmaap/simulator
       container_name: dmaap-simulator
       hostname: dmaap-simulator
-      ports:
-       - "3904:3904"
+      expose:
+       - 3904
    pap:
       image: nexus3.onap.org:10001/onap/policy-pap:${POLICY_PAP_VERSION}
       container_name: policy-pap
@@ -57,8 +54,8 @@ services:
        - message-router
        - pap
       hostname: policy-xacml-pdp
-      ports:
-       - "6969:6969"
+      expose:
+       - 6969
    start_dependencies:
       image: dadarek/wait-for-dependencies
       environment:
index c5a923d..90ffa23 100644 (file)
@@ -94,7 +94,7 @@ chmod -R 777 "${WORKSPACE}/data/clone"
 export ENV_NAME='CSIT'
 export MR_IP_ADDR='10.0.0.1'
 
-ifconfig
+ip a
 IP_ADDRESS=`ip route get 8.8.8.8 | awk '/src/{ print $7 }'`
 export HOST_IP="$IP_ADDRESS"
 
index 3e7d879..e96237c 100644 (file)
@@ -2,6 +2,10 @@
 REQUEST_TIMEOUT=5000
 OUTPUT_PATH=/var/certs
 CA_NAME=Invalid
+KEYSTORE_PATH=/etc/onap/aaf/certservice/certs/certServiceClient-keystore.jks
+KEYSTORE_PASSWORD=secret
+TRUSTSTORE_PATH=/etc/onap/aaf/certservice/certs/truststore.jks
+TRUSTSTORE_PASSWORD=secret
 #Csr config envs
 COMMON_NAME=onap.org
 ORGANIZATION=Linux-Foundation
index 0181896..55fefa3 100644 (file)
@@ -2,6 +2,10 @@
 REQUEST_TIMEOUT=30000
 OUTPUT_PATH=/var/certs
 CA_NAME=RA
+KEYSTORE_PATH=/etc/onap/aaf/certservice/certs/certServiceClient-keystore.jks
+KEYSTORE_PASSWORD=secret
+TRUSTSTORE_PATH=/etc/onap/aaf/certservice/certs/truststore.jks
+TRUSTSTORE_PASSWORD=secret
 #Csr config envs
 COMMON_NAME=onap.org
 ORGANIZATION=Linux-Foundation
index f9fc091..90ee1a3 100644 (file)
@@ -53,6 +53,11 @@ Cert Service Client successfully creates keystore and truststore
     [Documentation]  Run with correct env and expected exit code 0
     Run Cert Service Client And Validate JKS File Creation And Client Exit Code  ${VALID_ENV_FILE}  0
 
+Cert Service Client successfully creates keystore and truststore with expected data
+    [Tags]      AAF-CERT-SERVICE
+    [Documentation]  Run with correct env and JKS files created with correct data
+    Run Cert Service Client And Validate JKS Files Contain Expected Data  ${VALID_ENV_FILE}  0
+
 Run Cert Service Client Container And Validate Exit Code And API Response
     [Tags]      AAF-CERT-SERVICE
     [Documentation]  Run with invalid CaName env and expected exit code 5
index 792b693..a4a0df2 100644 (file)
@@ -2,11 +2,10 @@ import docker
 import os
 import shutil
 import re
-from OpenSSL import crypto
+from EnvsReader import EnvsReader
 from docker.types import Mount
 
 ARCHIVES_PATH = os.getenv("WORKSPACE") + "/archives/"
-MOUNT_PATH = os.getenv("WORKSPACE") + "/tests/aaf/certservice/tmp"
 
 ERROR_API_REGEX = 'Error on API response.*[0-9]{3}'
 RESPONSE_CODE_REGEX = '[0-9]{3}'
@@ -14,66 +13,43 @@ RESPONSE_CODE_REGEX = '[0-9]{3}'
 
 class CertClientManager:
 
+    def __init__(self, mount_path, truststore_path):
+        self.mount_path = mount_path
+        self.truststore_path = truststore_path
+
     def run_client_container(self, client_image, container_name, path_to_env, request_url, network):
         self.create_mount_dir()
         client = docker.from_env()
-        environment = self.read_list_env_from_file(path_to_env)
+        environment = EnvsReader().read_env_list_from_file(path_to_env)
         environment.append("REQUEST_URL=" + request_url)
         container = client.containers.run(
             image=client_image,
             name=container_name,
             environment=environment,
             network=network,
-            user='root', #Run container as root to avoid permission issues with volume mount access
-            mounts=[Mount(target='/var/certs', source=MOUNT_PATH, type='bind')],
+            user='root',  # Run container as root to avoid permission issues with volume mount access
+            mounts=[Mount(target='/var/certs', source=self.mount_path, type='bind'),
+                    Mount(target='/etc/onap/aaf/certservice/certs/', source=self.truststore_path, type='bind')],
             detach=True
         )
         exitcode = container.wait()
         return exitcode
 
-    def read_list_env_from_file(self, path):
-        f = open(path, "r")
-        r_list = []
-        for line in f:
-            line = line.strip()
-            if line[0] != "#":
-                r_list.append(line)
-        return r_list
-
     def remove_client_container_and_save_logs(self, container_name, log_file_name):
         client = docker.from_env()
         container = client.containers.get(container_name)
-        text_file = open(ARCHIVES_PATH + "container_" + log_file_name + ".log", "w")
+        text_file = open(ARCHIVES_PATH + "client_container_" + log_file_name + ".log", "w")
         text_file.write(container.logs())
         text_file.close()
         container.remove()
         self.remove_mount_dir()
 
-    def can_open_keystore_and_truststore_with_pass(self):
-        keystore_pass_path = MOUNT_PATH + '/keystore.pass'
-        keystore_jks_path = MOUNT_PATH + '/keystore.jks'
-        can_open_keystore = self.can_open_jks_file_by_pass_file(keystore_pass_path, keystore_jks_path)
-
-        truststore_pass_path = MOUNT_PATH + '/truststore.pass'
-        truststore_jks_path = MOUNT_PATH + '/truststore.jks'
-        can_open_truststore = self.can_open_jks_file_by_pass_file(truststore_pass_path, truststore_jks_path)
-
-        return can_open_keystore & can_open_truststore
-
-    def can_open_jks_file_by_pass_file(self, pass_file_path, jks_file_path):
-        try:
-            password = open(pass_file_path, 'rb').read()
-            crypto.load_pkcs12(open(jks_file_path, 'rb').read(), password)
-            return True
-        except:
-            return False
-
     def create_mount_dir(self):
-        if not os.path.exists(MOUNT_PATH):
-            os.makedirs(MOUNT_PATH)
+        if not os.path.exists(self.mount_path):
+            os.makedirs(self.mount_path)
 
     def remove_mount_dir(self):
-        shutil.rmtree(MOUNT_PATH)
+        shutil.rmtree(self.mount_path)
 
     def can_find_api_response_in_logs(self, container_name):
         logs = self.get_container_logs(container_name)
diff --git a/tests/aaf/certservice/libraries/EnvsReader.py b/tests/aaf/certservice/libraries/EnvsReader.py
new file mode 100644 (file)
index 0000000..cc60eed
--- /dev/null
@@ -0,0 +1,11 @@
+
+class EnvsReader:
+
+  def read_env_list_from_file(self, path):
+    f = open(path, "r")
+    r_list = []
+    for line in f:
+      line = line.strip()
+      if line[0] != "#":
+        r_list.append(line)
+    return r_list
diff --git a/tests/aaf/certservice/libraries/JksFilesValidator.py b/tests/aaf/certservice/libraries/JksFilesValidator.py
new file mode 100644 (file)
index 0000000..8c150de
--- /dev/null
@@ -0,0 +1,70 @@
+from OpenSSL import crypto
+from cryptography.x509.oid import ExtensionOID
+from cryptography import x509
+from EnvsReader import EnvsReader
+
+class JksFilesValidator:
+
+  def __init__(self, mount_path):
+    self.keystorePassPath = mount_path + '/keystore.pass'
+    self.keystoreJksPath = mount_path + '/keystore.jks'
+    self.truststorePassPath = mount_path + '/truststore.pass'
+    self.truststoreJksPath = mount_path + '/truststore.jks'
+
+  def get_and_compare_data(self, path_to_env):
+    data = self.get_data(path_to_env)
+    return data, self.contains_expected_data(data)
+
+  def can_open_keystore_and_truststore_with_pass(self):
+    can_open_keystore = self.can_open_jks_file_with_pass_file(self.keystorePassPath, self.keystoreJksPath)
+    can_open_truststore = self.can_open_jks_file_with_pass_file(self.truststorePassPath, self.truststoreJksPath)
+
+    return can_open_keystore & can_open_truststore
+
+  def can_open_jks_file_with_pass_file(self, pass_file_path, jks_file_path):
+    try:
+      self.get_certificate(pass_file_path, jks_file_path)
+      return True
+    except:
+      return False
+
+  def get_data(self, path_to_env):
+    envs = self.get_envs_as_dict(EnvsReader().read_env_list_from_file(path_to_env))
+    certificate = self.get_certificate(self.keystorePassPath, self.keystoreJksPath)
+    data = self.get_owner_data_from_certificate(certificate)
+    data['SANS'] = self.get_sans(certificate)
+    return type('', (object,), {"expectedData": envs, "actualData": data})
+
+  def contains_expected_data(self, data):
+    expectedData = data.expectedData
+    actualData = data.actualData
+    return cmp(expectedData, actualData) == 0
+
+  def get_owner_data_from_certificate(self, certificate):
+    list = certificate.get_subject().get_components()
+    return dict((k, v) for k, v in list)
+
+  def get_certificate(self, pass_file_path, jks_file_path):
+    password = open(pass_file_path, 'rb').read()
+    crypto.load_pkcs12(open(jks_file_path, 'rb').read(), password)
+    return crypto.load_pkcs12(open(jks_file_path, 'rb').read(), password).get_certificate()
+
+  def get_sans(self, cert):
+    extension = cert.to_cryptography().extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
+    dnsList = extension.value.get_values_for_type(x509.DNSName)
+    return ':'.join(map(lambda dns: dns.encode('ascii','ignore'), dnsList))
+
+  def get_envs_as_dict(self, list):
+    envs = self.get_list_of_pairs_by_mappings(list)
+    return self.remove_nones_from_dict(envs)
+
+  def remove_nones_from_dict(self, dictionary):
+    return dict((k, v) for k, v in dictionary.iteritems() if k is not None)
+
+  def get_list_of_pairs_by_mappings(self, list):
+    mappings = self.get_mappings()
+    listOfEnvs = map(lambda k: k.split('='), list)
+    return dict((mappings.get(a[0]), a[1]) for a in listOfEnvs)
+
+  def get_mappings(self):
+    return {'COMMON_NAME':'CN', 'ORGANIZATION':'O', 'ORGANIZATION_UNIT':'OU', 'LOCATION':'L', 'STATE':'ST', 'COUNTRY':'C', 'SANS':'SANS'}
index 75cebad..d4d4fd9 100644 (file)
@@ -1,22 +1,24 @@
 *** Settings ***
 
+Resource          ../../../common.robot
+Resource          ./cert-service-properties.robot
 Library              RequestsLibrary
 Library           HttpLibrary.HTTP
 Library           Collections
-Library           ../libraries/CertClientManager.py
-Resource          ../../../common.robot
-Resource          ./cert-service-properties.robot
+Library           ../libraries/CertClientManager.py  ${MOUNT_PATH}  ${TRUSTSTORE_PATH}
+Library           ../libraries/JksFilesValidator.py  ${MOUNT_PATH}
 
 *** Keywords ***
 
 Create sessions
     [Documentation]  Create all required sessions
-    Create Session    aaf_cert_service_url    ${AAFCERT_URL}
-    Set Suite Variable    ${http_session}    aaf_cert_service_url
+    ${certs}=  Create List  ${CERTSERVICE_SERVER_CRT}  ${CERTSERVICE_SERVER_KEY}
+    Create Client Cert Session  alias  ${AAFCERT_URL}  client_certs=${certs}  verify=${ROOTCA}
+    Set Suite Variable  ${https_valid_cert_session}  alias
 
 Run Healthcheck
     [Documentation]  Run Healthcheck
-    ${resp}=   Get Request     ${http_session}         /actuator/health
+    ${resp}=  Get Request      ${https_valid_cert_session}     /actuator/health
     Should Be Equal As Strings         ${resp.status_code}     200
     Validate Recieved Response  ${resp}  status  UP
 
@@ -30,7 +32,7 @@ Validate Recieved Response
 Send Get Request And Validate Response
     [Documentation]   Send request to passed url and validate received response
     [Arguments]   ${path}  ${resp_code}
-    ${resp}=   Get Request     ${http_session}  ${path}
+    ${resp}=   Get Request     ${https_valid_cert_session}  ${path}
     Should Be Equal As Strings         ${resp.status_code}     ${resp_code}
 
 Send Get Request with Header
@@ -38,7 +40,7 @@ Send Get Request with Header
     [Arguments]  ${path}  ${csr_file}  ${pk_file}
     [Return]  ${resp}
     ${headers}=  Create Header with CSR and PK  ${csr_file}  ${pk_file}
-    ${resp}=   Get Request     ${http_session}  ${path}  headers=${headers}
+    ${resp}=   Get Request     ${https_valid_cert_session}  ${path}  headers=${headers}
 
 Send Get Request with Header And Expect Success
     [Documentation]   Send request to passed url and validate received response
@@ -80,7 +82,7 @@ Create Header with CSR and PK
 Send Post Request And Validate Response
     [Documentation]   Send request to passed url and validate received response
     [Arguments]   ${path}  ${resp_code}
-    ${resp}=   Post Request    ${http_session}  ${path}
+    ${resp}=   Post Request    ${https_valid_cert_session}  ${path}
     Should Be Equal As Strings         ${resp.status_code}     ${resp_code}
 
 Run Cert Service Client And Validate JKS File Creation And Client Exit Code
@@ -92,6 +94,15 @@ Run Cert Service Client And Validate JKS File Creation And Client Exit Code
     Should Be Equal As Strings  ${exit_code}  ${expected_exit_code}  Client return: ${exitcode} exit code, but expected: ${expected_exit_code}
     Should Be True  ${can_open}  Cannot Open Keystore/TrustStore by passpshase
 
+Run Cert Service Client And Validate JKS Files Contain Expected Data
+    [Documentation]  Run Cert Service Client Container And Validate JKS Files Contain Expected Data
+    [Arguments]  ${env_file}  ${expected_exit_code}
+    ${exit_code}=  Run Client Container  ${DOCKER_CLIENT_IMAGE}  ${CLIENT_CONTAINER_NAME}  ${env_file}  ${CERT_SERVICE_ADDRESS}${CERT_SERVICE_ENDPOINT}  ${CERT_SERVICE_NETWORK}
+    ${data}    ${isEqual}=  Get And Compare Data  ${env_file}
+    Remove Client Container And Save Logs  ${CLIENT_CONTAINER_NAME}  positive_path_with_data
+    Should Be Equal As Strings  ${exit_code}  ${expected_exit_code}  Client return: ${exitcode} exit code, but expected: ${expected_exit_code}
+    Should Be True  ${isEqual}  Keystore doesn't contain ${data.expectedData}. Actual data is: ${data.actualData}
+
 Run Cert Service Client And Validate Http Response Code And Client Exit Code
     [Documentation]  Run Cert Service Client Container And Validate Exit Code
     [Arguments]   ${env_file}  ${expected_api_response_code}  ${expected_exit_code}
index 5fd2d8a..53d6b24 100644 (file)
@@ -1,10 +1,14 @@
 *** Variables ***
 
-${CERT_SERVICE_PORT}                     8080
-${AAFCERT_URL}                           http://localhost:${cert_service_port}
+${CERT_SERVICE_CONTAINER_NAME}           aaf-cert-service
+${CERT_SERVICE_PORT}                     8443
+${AAFCERT_URL}                           https://localhost:${cert_service_port}
 ${CLIENT_CA_NAME}                        Client
 ${RA_CA_NAME}                            RA
 ${CERT_SERVICE_ENDPOINT}                 /v1/certificate/
+${ROOTCA}                                %{WORKSPACE}/tests/aaf/certservice/assets/certs/root.crt
+${CERTSERVICE_SERVER_CRT}                %{WORKSPACE}/tests/aaf/certservice/assets/certs/certServiceServer.crt
+${CERTSERVICE_SERVER_KEY}                %{WORKSPACE}/tests/aaf/certservice/assets/certs/certServiceServer.key
 ${VALID_CLIENT_CSR_FILE}                 %{WORKSPACE}/tests/aaf/certservice/assets/valid_client.csr
 ${VALID_CLIENT_PK_FILE}                  %{WORKSPACE}/tests/aaf/certservice/assets/valid_client.pk
 ${VALID_RA_CSR_FILE}                     %{WORKSPACE}/tests/aaf/certservice/assets/valid_ra.csr
@@ -13,9 +17,11 @@ ${INVALID_CSR_FILE}                      %{WORKSPACE}/tests/aaf/certservice/asse
 ${INVALID_PK_FILE}                       %{WORKSPACE}/tests/aaf/certservice/assets/invalid.key
 
 
-${CERT_SERVICE_ADDRESS}                  http://%{AAFCERT_IP}:${cert_service_port}
+${CERT_SERVICE_ADDRESS}                  https://${CERT_SERVICE_CONTAINER_NAME}:${CERT_SERVICE_PORT}
 ${VALID_ENV_FILE}                        %{WORKSPACE}/tests/aaf/certservice/assets/valid_client_docker.env
 ${INVALID_ENV_FILE}                      %{WORKSPACE}/tests/aaf/certservice/assets/invalid_client_docker.env
 ${DOCKER_CLIENT_IMAGE}                   nexus3.onap.org:10001/onap/org.onap.aaf.certservice.aaf-certservice-client:latest
 ${CLIENT_CONTAINER_NAME}                 %{ClientContainerName}
 ${CERT_SERVICE_NETWORK}                  certservice_certservice
+${MOUNT_PATH}                            %{WORKSPACE}/tests/aaf/certservice/tmp
+${TRUSTSTORE_PATH}                       %{WORKSPACE}/plans/aaf/certservice/certs
diff --git a/tests/dcaegen2/testcases/assets/json_events/CommonEventFormat_28.3.json b/tests/dcaegen2/testcases/assets/json_events/CommonEventFormat_28.3.json
deleted file mode 100644 (file)
index 90f6d81..0000000
+++ /dev/null
@@ -1,1866 +0,0 @@
-{
-    "$schema": "http://json-schema.org/draft-04/schema#",
-       
-       "definitions": {
-       "attCopyrightNotice": {
-                       "description": "Copyright (c) <2017>, AT&T Intellectual Property. All rights reserved. Licensed under the Apache License, Version 2.0 (the License)",
-                       "type": "object",
-                       "properties": {
-                               "useAndRedistribution": {
-                                       "description": "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",
-                                       "type": "string"
-                               },
-                               "licenseLink": {
-                                "description": "http://www.apache.org/licenses/LICENSE-2.0",
-                                "type":"string"
-                               },
-                               "condition1": {
-                                       "description": "Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an AS IS BASIS,",
-                                       "type": "string"
-                               },
-                               "condition2": {
-                                       "description": "Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.",
-                                       "type": "string"
-                               },
-                               "condition3": {
-                                       "description": "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
-                                       "type": "string"
-                               },
-                               "condition4": {
-                                       "description": "See the License for the specific language governing permissions and limitations under the License.",
-                                       "type": "string"
-                               },
-                               "Trademarks": {
-                                       "description": "ECOMP and OpenECOMP are trademarks and service marks of AT&T Intellectual Property.",
-                                       "type": "string"
-                               }
-                       }
-               },
-       
-               "codecsInUse": {
-                       "description": "number of times an identified codec was used over the measurementInterval",
-                       "type": "object",
-                       "properties": {
-                               "codecIdentifier": { "type": "string" },
-                               "numberInUse": { "type": "integer" }
-                       },
-                       "required": [ "codecIdentifier", "numberInUse" ]
-               },
-               "command": {
-                       "description": "command from an event collector toward an event source",
-                       "type": "object",
-                       "properties": {
-                               "commandType": {
-                                       "type": "string",
-                                       "enum": [
-                                               "heartbeatIntervalChange",
-                                               "measurementIntervalChange",
-                                               "provideThrottlingState",
-                                               "throttlingSpecification"
-                                       ]
-                               },
-                               "eventDomainThrottleSpecification": { "$ref": "#/definitions/eventDomainThrottleSpecification" },
-                               "heartbeatInterval": { "type": "integer" },
-                               "measurementInterval": { "type": "integer" }
-                       },
-                       "required": [ "commandType" ]
-               },
-               "commandList": {
-                       "description": "array of commands from an event collector toward an event source",
-                       "type": "array",
-                       "items": {
-                           "$ref": "#/definitions/command"
-                       },
-                       "minItems": 0
-               },
-               "commonEventHeader": {
-                       "description": "fields common to all events",
-                       "type": "object",
-                       "properties": {
-                               "domain": {
-                                       "description": "the eventing domain associated with the event",
-                                       "type": "string",
-                                       "enum": [
-                                               "fault",
-                                               "heartbeat",
-                                               "measurementsForVfScaling",
-                                               "mobileFlow",
-                                               "other",
-                                               "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 - applicationVnf, 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 vnf naming standards",
-                                       "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"
-                               },
-                               "version": {
-                                       "description": "version of the event header",
-                                       "type": "number"
-                               }
-                       },
-                       "required": [ "domain", "eventId", "eventName", "lastEpochMicrosec", 
-                                                 "priority", "reportingEntityName", "sequence", "sourceName",
-                                     "startEpochMicrosec", "version" ]
-               },
-               "counter": {
-                       "description": "performance counter",
-                       "type": "object",
-                       "properties": {
-                               "criticality": { "type": "string", "enum": [ "CRIT", "MAJ" ] },
-                               "name":  { "type": "string" },
-                               "thresholdCrossed": { "type": "string" },
-                               "value": { "type": "string"}
-                       },
-                       "required": [ "criticality", "name", "thresholdCrossed", "value" ]
-               },
-               "cpuUsage": {
-                       "description": "usage of an identified CPU",
-                       "type": "object",
-                       "properties": {
-                               "cpuIdentifier": { 
-                    "description": "cpu identifer",
-                    "type": "string" 
-                },
-                               "cpuIdle": { 
-                    "description": "percentage of CPU time spent in the idle task",
-                    "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 VNFC reporting the event is running",
-                    "type": "number" 
-                }
-                       },
-                       "required": [ "cpuIdentifier", "percentUsage" ]
-               },
-               "diskUsage": {
-                       "description": "usage of an identified disk",
-                       "type": "object",
-                       "properties": {
-                               "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"
-                },
-                "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"
-                }
-                       },
-                       "required": [ "diskIdentifier" ]
-               },
-        "endOfCallVqmSummaries": {
-            "description": "provides end of call voice quality metrics",
-                       "type": "object",
-                       "properties": {
-                "adjacencyName": {
-                    "description": " adjacency name",
-                    "type": "string"
-                },
-                "endpointDescription": {
-                    "description": "Either Caller or Callee",
-                    "type": "string",
-                    "enum": ["Caller", "Callee"]
-                },
-                "endpointJitter": {
-                    "description": "",
-                    "type": "number"
-                },
-                "endpointRtpOctetsDiscarded": {
-                    "description": "",
-                    "type": "number"
-                },
-                "endpointRtpOctetsReceived": {
-                    "description": "",
-                    "type": "number"
-                },
-                "endpointRtpOctetsSent": {
-                    "description": "",
-                    "type": "number"
-                },
-                "endpointRtpPacketsDiscarded": {
-                    "description": "",
-                    "type": "number"
-                },
-                "endpointRtpPacketsReceived": {
-                    "description": "",
-                    "type": "number"
-                },
-                "endpointRtpPacketsSent": {
-                    "description": "",
-                    "type": "number"
-                },
-                "localJitter": {
-                    "description": "",
-                    "type": "number"
-                },
-                "localRtpOctetsDiscarded": {
-                    "description": "",
-                    "type": "number"
-                },
-                "localRtpOctetsReceived": {
-                    "description": "",
-                    "type": "number"
-                },
-                "localRtpOctetsSent": {
-                    "description": "",
-                    "type": "number"
-                },
-                "localRtpPacketsDiscarded": {
-                    "description": "",
-                    "type": "number"
-                },
-                "localRtpPacketsReceived": {
-                    "description": "",
-                    "type": "number"
-                },
-                "localRtpPacketsSent": {
-                    "description": "",
-                    "type": "number"
-                },
-                "mosCqe": {
-                    "description": "1-5 1dp",
-                    "type": "number"
-                },
-                "packetsLost": {
-                    "description": "",
-                    "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"
-                }
-            },
-            "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" },
-                       "measurementsForVfScalingFields": { "$ref": "#/definitions/measurementsForVfScalingFields" },
-                               "mobileFlowFields": { "$ref": "#/definitions/mobileFlowFields" },
-                       "otherFields": { "$ref": "#/definitions/otherFields" },
-                       "sipSignalingFields": { "$ref": "#/definitions/sipSignalingFields" },
-                       "stateChangeFields": { "$ref": "#/definitions/stateChangeFields" },
-                               "syslogFields": { "$ref": "#/definitions/syslogFields" },
-                       "thresholdCrossingAlertFields": { "$ref": "#/definitions/thresholdCrossingAlertFields" },
-                       "voiceQualityFields": { "$ref": "#/definitions/voiceQualityFields" }
-               },
-            "required": [ "commonEventHeader" ]
-        },
-               "eventDomainThrottleSpecification": {
-                       "description": "specification of what information to suppress within an event domain",
-                       "type": "object",
-                       "properties": {
-                       "eventDomain": {
-                               "description": "Event domain enum from the commonEventHeader domain field",
-                               "type": "string"
-                       },
-                       "suppressedFieldNames": {
-                               "description": "List of optional field names in the event block that should not be sent to the Event Listener",
-                               "type": "array",
-                                       "items": {
-                                           "type": "string"
-                                       }
-                       },
-                               "suppressedNvPairsList": {
-                                       "description": "Optional list of specific NvPairsNames to suppress within a given Name-Value Field",
-                               "type": "array",
-                                       "items": {
-                                           "$ref": "#/definitions/suppressedNvPairs"
-                                       }
-                       }
-                       },
-                       "required": [ "eventDomain" ]
-               },
-               "eventDomainThrottleSpecificationList": {
-                       "description": "array of eventDomainThrottleSpecifications",
-                       "type": "array",
-                       "items": {
-                           "$ref": "#/definitions/eventDomainThrottleSpecification"
-                       },
-                       "minItems": 0
-               },
-               "eventList": {
-                       "description": "array of events",
-                       "type": "array",
-                       "items": {
-                               "$ref": "#/definitions/event"
-                       }
-               },
-               "eventThrottlingState": {
-                       "description": "reports the throttling in force at the event source",
-                       "type": "object",
-                       "properties": {
-                       "eventThrottlingMode": {
-                               "description": "Mode the event manager is in",
-                               "type": "string",
-                                       "enum": [
-                                               "normal",
-                                               "throttled"
-                                       ]
-                       },
-                               "eventDomainThrottleSpecificationList": { "$ref": "#/definitions/eventDomainThrottleSpecificationList" }
-                       },
-                       "required": [ "eventThrottlingMode" ]
-               },
-               "faultFields": {
-                       "description": "fields specific to fault events",
-                       "type": "object",
-                       "properties": {
-                               "alarmAdditionalInformation": {
-                                       "description": "additional alarm information",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/field"
-                                       }
-                               },
-                               "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": "number"
-                               },
-                               "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"
-                                       ]
-                               }
-                       },
-                       "required": [ "alarmCondition", "eventSeverity", "eventSourceType",
-                                     "faultFieldsVersion", "specificProblem", "vfStatus" ]
-               },
-               "featuresInUse": {
-                       "description": "number of times an identified feature was used over the measurementInterval",
-                       "type": "object",
-                       "properties": {
-                               "featureIdentifier": { "type": "string" },
-                               "featureUtilization": { "type": "integer" }
-                       },
-                       "required": [ "featureIdentifier", "featureUtilization" ]
-               },
-               "field": {
-                       "description": "name value pair",
-                       "type": "object",
-                       "properties": {
-                               "name":  { "type": "string" },
-                               "value": { "type": "string" }
-                       },
-                       "required": [ "name", "value" ]
-               },
-               "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" }
-                       },
-                       "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": {
-                                       "description": "array of key: value pairs where the keys are drawn from the IP Type-of-Service identifiers which range from '0' to '255', and the values are the count of packets that had those ToS identifiers in the flow",
-                    "type": "array",
-                    "items": {
-                                               "type": "array",
-                                               "items": [
-                                                       { "type": "string" },
-                                                       { "type": "number" }
-                                               ]
-                                       }
-                               },
-                               "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": {
-                                       "description": "array of key: value pairs where the keys are drawn from LTE QCI or UMTS class of service strings, and the values are the count of packets that had those strings in the flow",
-                    "type": "array",
-                    "items": {
-                                               "type": "array",
-                                               "items": [
-                                                       { "type": "string" },
-                                                       { "type": "number" }
-                                               ]
-                                       }
-                               },
-                               "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": {
-                                       "description": "array of key: value pairs where the keys are drawn from TCP Flags and the values are the count of packets that had that TCP Flag in the flow",
-                    "type": "array",
-                    "items": {
-                                               "type": "array",
-                                               "items": [
-                                                       { "type": "string" },
-                                                       { "type": "number" }
-                                               ]
-                                       }
-                               },
-                               "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"
-                               }
-                       },
-                       "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"
-                       ]
-               },
-               "heartbeatFields": {
-                       "description": "optional field block for fields specific to heartbeat events",
-                       "type": "object",
-                       "properties": {
-                               "additionalFields": {
-                                       "description": "additional heartbeat fields if needed",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/field"
-                                       }
-                               },
-                               "heartbeatFieldsVersion": {
-                                       "description": "version of the heartbeatFields block",
-                                       "type": "number"
-                               },
-                               "heartbeatInterval": {
-                                       "description": "current heartbeat interval in seconds",
-                                       "type": "integer"
-                               }
-                       },
-                       "required": [ "heartbeatFieldsVersion", "heartbeatInterval" ]
-               },
-               "internalHeaderFields": {
-                       "description": "enrichment fields for internal VES Event Listener service use only, not supplied by event sources",
-                       "type": "object"
-               },
-               "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" 
-                }
-                       },
-                       "required": [ "objectInstances", "objectName" ]
-               },
-               "jsonObjectInstance": {
-                       "description": "meta-information about an instance of a jsonObject along with the actual object instance",
-                       "type": "object",
-                       "properties": {
-                               "objectInstance":  {
-                    "description": "an instance conforming to the jsonObject schema", 
-                    "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"
-                    }                                  
-                }
-                       },
-                       "required": [ "objectInstance" ]
-               },
-               "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" 
-                               }
-                       },
-                       "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" }
-                       },
-                       "required": [ "countsInTheBucket" ]
-               },
-               "measurementsForVfScalingFields": {
-                       "description": "measurementsForVfScaling fields",
-                       "type": "object",
-                       "properties": {
-                               "additionalFields": {
-                                       "description": "additional name-value-pair fields",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/field"
-                                       }
-                               },
-                               "additionalMeasurements": {
-                                       "description": "array of named name-value-pair arrays",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/namedArrayOfFields"
-                                       }
-                               },
-                "additionalObjects": {
-                    "description": "array of JSON objects described by name, schema and other meta-information",
-                                       "type": "array",
-                                       "items": {
-                        "$ref": "#/definitions/jsonObject"
-                                       }
-                },
-                               "codecUsageArray": {
-                                       "description": "array of codecs in use",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/codecsInUse"
-                                       }
-                               },
-                               "concurrentSessions": {
-                                       "description": "peak concurrent sessions for the VM or VNF 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 VNF",
-                                       "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": {
-                                       "description": "array of features in use",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/featuresInUse"
-                                       }
-                               },
-                               "filesystemUsageArray": {
-                                       "description": "filesystem usage of the VM on which the VNFC reporting the event is running",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/filesystemUsage"
-                                       }
-                               },
-                               "latencyDistribution": {
-                                       "description": "array of integers representing counts of requests whose latency in milliseconds falls within per-VNF configured ranges",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/latencyBucketMeasure"
-                                       }
-                               },
-                               "meanRequestLatency": {
-                                       "description": "mean seconds required to respond to each request for the VM on which the VNFC reporting the event is running",
-                                       "type": "number"
-                               },
-                               "measurementInterval": {
-                                       "description": "interval over which measurements are being reported in seconds",
-                                       "type": "number"
-                               },
-                               "measurementsForVfScalingVersion": {
-                                       "description": "version of the measurementsForVfScaling block",
-                                       "type": "number"
-                               },
-                               "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 VNF over the measurementInterval",
-                                       "type": "number"
-                               },
-                               "vnfcScalingMetric": {
-                                       "description": "represents busy-ness of the VNF from 0 to 100 as reported by the VNFC",
-                                       "type": "integer"
-                               },
-                               "vNicPerformanceArray": {
-                                       "description": "usage of an array of virtual network interface cards",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/vNicPerformance"
-                                       }
-                               }
-                       },
-                       "required": [ "measurementInterval", "measurementsForVfScalingVersion" ]
-               },
-               "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 VNFC reporting the event is running", 
-                    "type": "number" 
-                },
-                               "memoryFree": { 
-                    "description": "kibibytes of physical RAM left unused by the system", 
-                    "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" 
-                },
-                               "memoryUsed": { 
-                    "description": "total memory minus the sum of free, buffered, cached and slab memory measured in kibibytes", 
-                    "type": "number" 
-                },
-                               "vmIdentifier": { 
-                    "description": "virtual machine identifier associated with the memory metrics", 
-                    "type": "string" 
-                }
-                       },
-                       "required": [ "memoryFree", "memoryUsed", "vmIdentifier" ]
-               },
-               "mobileFlowFields": {
-                       "description": "mobileFlow fields",
-                       "type": "object",
-                       "properties": {
-                               "additionalFields": {
-                                       "description": "additional mobileFlow fields if needed",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/field"
-                                       }
-                               },
-                               "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": "number"
-                },
-                               "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"
-                               }
-                       },
-                       "required": [ "flowDirection", "gtpPerFlowMetrics", "ipProtocolType", "ipVersion",
-                                     "mobileFlowFieldsVersion", "otherEndpointIpAddress", "otherEndpointPort",
-                                     "reportingEndpointIpAddr", "reportingEndpointPort" ]
-               },
-               "namedArrayOfFields": {
-                       "description": "an array of name value pairs along with a name for the array",
-                       "type": "object",
-                       "properties": {
-                               "name":  { "type": "string" },
-                               "arrayOfFields": {
-                                       "description": "array of name value pairs",
-                                       "type": "array",
-                                       "items": {  
-                                               "$ref": "#/definitions/field" 
-                                       }
-                               }
-                       },
-                       "required": [ "name", "arrayOfFields" ]
-               },
-               "otherFields": {
-                       "description": "fields for events belonging to the 'other' domain of the commonEventHeader domain enumeration",
-                       "type": "object",
-                       "properties": {
-                               "hashOfNameValuePairArrays": {
-                                       "description": "array of named name-value-pair arrays",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/namedArrayOfFields"
-                                       }
-                               },
-                "jsonObjects": {
-                    "description": "array of JSON objects described by name, schema and other meta-information",
-                                       "type": "array",
-                                       "items": {
-                        "$ref": "#/definitions/jsonObject"
-                                       }
-                },
-                               "nameValuePairs": {
-                                       "description": "array of name-value pairs",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/field"
-                                       }
-                               },                              
-                "otherFieldsVersion": {
-                    "description": "version of the otherFields block",
-                    "type": "number"
-                }
-            },
-            "required": [ "otherFieldsVersion" ]
-               },
-               "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 <variables> 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"
-                               }
-                       },
-                       "required": [ "messageId", "text" ]
-               },
-        "sipSignalingFields": {
-            "description": "sip signaling fields",
-            "type": "object",
-            "properties": {
-                "additionalInformation": {
-                                       "description": "additional sip signaling fields if needed",
-                                       "type": "array",
-                                       "items": {  
-                                               "$ref": "#/definitions/field" 
-                                       }
-                },
-                "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 VNF",
-                    "type": "string"
-                },
-                "localPort": {
-                    "description": "port on VNF",
-                    "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": "number"
-                },
-                "summarySip": {
-                    "description": "the SIP Method or Response (‘INVITE’, â€˜200 OK’, â€˜BYE’, etc)",
-                    "type": "string"
-                },
-                "vendorVnfNameFields": {
-                    "$ref": "#/definitions/vendorVnfNameFields"
-                }
-            },
-            "required": [ "correlator", "localIpAddress", "localPort", "remoteIpAddress", 
-                                     "remotePort", "sipSignalingFieldsVersion", "vendorVnfNameFields" ]
-        },
-               "stateChangeFields": {
-                       "description": "stateChange fields",
-                       "type": "object",
-                       "properties": {
-                               "additionalFields": {
-                                       "description": "additional stateChange fields if needed",
-                                       "type": "array",
-                                       "items": {
-                                               "$ref": "#/definitions/field"
-                                       }
-                               },
-                               "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": "number"
-                               },
-                               "stateInterface": {
-                                       "description": "card or port name of the entity that changed state",
-                                       "type": "string"
-                               }
-                       },
-                       "required": [ "newState", "oldState", "stateChangeFieldsVersion", "stateInterface" ]
-               },
-               "suppressedNvPairs": {
-                       "description": "List of specific NvPairsNames to suppress within a given Name-Value Field for event Throttling",
-                       "type": "object",
-                       "properties": {
-                               "nvPairFieldName": {
-                                       "description": "Name of the field within which are the nvpair names to suppress",
-                                       "type": "string"
-                               },
-                               "suppressedNvPairNames": {
-                                       "description": "Array of nvpair names to suppress within the nvpairFieldName",
-                               "type": "array",
-                                       "items": {
-                                           "type": "string"
-                                       }
-                               }
-                       },
-                       "required": [ "nvPairFieldName", "suppressedNvPairNames" ]
-               },
-               "syslogFields": {
-                       "description": "sysLog fields",
-                       "type": "object",
-                       "properties": {
-                               "additionalFields": {
-                                       "description": "additional syslog fields if needed provided as name=value delimited by a pipe â€˜|’ symbol, for example: 'name1=value1|name2=value2|…'",
-                                       "type": "string"
-                               },
-                               "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": "number"
-                               },
-                               "syslogMsg": {
-                                       "description": "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"
-                               },
-                               "syslogVer": {
-                                       "description": "IANA assigned version of the syslog protocol specification - typically 1",
-                                       "type": "number"
-                               }
-                       },
-                       "required": [ "eventSourceType", "syslogFieldsVersion", "syslogMsg", "syslogTag" ]
-               },
-               "thresholdCrossingAlertFields": {
-                       "description": "fields specific to threshold crossing alert events",
-                       "type": "object",
-                       "properties": {
-                               "additionalFields": {
-                                       "description": "additional threshold crossing alert fields if needed",
-                                       "type": "array",
-                                       "items": {  
-                                               "$ref": "#/definitions/field" 
-                                       }
-                               },
-                               "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": "number"
-                               }
-                       },
-                       "required": [
-                               "additionalParameters",
-                               "alertAction",
-                               "alertDescription",
-                               "alertType",
-                               "collectionTimestamp",
-                               "eventSeverity",
-                               "eventStartTimestamp",
-                               "thresholdCrossingFieldsVersion"
-                       ]
-               },
-               "vendorVnfNameFields": {
-                       "description": "provides vendor, vnf and vfModule identifying information",
-                       "type": "object",
-                       "properties": {
-                               "vendorName": {
-                                       "description": "VNF vendor name",
-                                       "type": "string"
-                               },
-                               "vfModuleName": {
-                                       "description": "ASDC vfModuleName for the vfModule generating the event",
-                                       "type": "string"
-                               },
-                               "vnfName": {
-                                       "description": "ASDC modelName for the VNF generating the event",
-                                       "type": "string"
-                               }
-                       },
-                       "required": [ "vendorName" ]
-               },
-               "vNicPerformance": {
-                       "description": "describes the performance and errors of an identified virtual network interface card",
-                       "type": "object",
-                       "properties": {
-                               "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"
-                               },
-                               "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"
-                               },
-                               "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"
-                               },
-                               "valuesAreSuspect": {
-                                       "description": "Indicates whether vNicPerformance values are likely inaccurate due to counter overflow or other condtions",
-                                       "type": "string",
-                                       "enum": [ "true", "false" ]
-                               },
-                               "vNicIdentifier": {
-                                       "description": "vNic identification",
-                                       "type": "string"
-                               }
-                       },
-                       "required": [ "valuesAreSuspect", "vNicIdentifier" ]
-               },
-        "voiceQualityFields": {
-            "description": "provides statistics related to customer facing voice products",
-            "type": "object",
-            "properties": {
-                "additionalInformation": {
-                                       "description": "additional voice quality fields if needed",
-                                       "type": "array",
-                                       "items": {  
-                                               "$ref": "#/definitions/field" 
-                                       }
-                },
-                "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"
-                },
-                "vendorVnfNameFields": {
-                    "$ref": "#/definitions/vendorVnfNameFields"
-                },
-                "voiceQualityFieldsVersion": {
-                    "description": "version of the voiceQualityFields block",
-                    "type": "number"
-                }
-            },
-            "required": [ "calleeSideCodec", "callerSideCodec", "correlator", "midCallRtcp",
-                                     "vendorVnfNameFields", "voiceQualityFieldsVersion" ]
-        }
-       },
-       "title": "Event Listener",
-       "type": "object",
-       "properties": {
-        "event": {"$ref": "#/definitions/event"}
-    }
-}
diff --git a/tests/dcaegen2/testcases/assets/json_events/CommonEventFormat_30.1.1.json b/tests/dcaegen2/testcases/assets/json_events/CommonEventFormat_30.1.1.json
new file mode 100644 (file)
index 0000000..286861c
--- /dev/null
@@ -0,0 +1,3052 @@
+{
+  "$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": "tl2972",
+          "type": "string"
+        },
+        "schemaDate": {
+          "description": "January 28, 2020",
+          "type": "string"
+        },
+        "schemaVersion": {
+          "description": "30.1.1",
+          "type": "number"
+        }
+      }
+    },
+    "schemaLicenseAndCopyrightNotice": {
+      "description": "Copyright (c) 2020, 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",
+            "perf3gpp",
+            "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",
+            "4.0.1",
+            "4.1"
+          ]
+        },
+        "vesEventListenerVersion": {
+          "description": "version of the VES Event Listener API",
+          "type": "string",
+          "enum": [
+            "7.0",
+            "7.0.1",
+            "7.1",
+            "7.1.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"
+        },
+        "perf3gppFields": {
+          "$ref": "#/definitions/perf3gppFields"
+        },
+        "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": "string"
+        },
+        "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": {
+        "globalAggregateTemperatureMarginIdentifier": {
+          "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": [
+        "globalAggregateTemperatureMarginIdentifier",
+        "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"
+      ]
+    },
+    "measDataCollection": {
+      "description": "3GPP measurement collection structure aligned with 3GPP PM format",
+      "type": "object",
+      "properties": {
+        "formatVersion": {
+          "description": "3gpp PM reporting file format version from pre-standard TS 28.550 v2.0.0",
+          "type": "string"
+        },
+        "granularityPeriod": {
+          "description": "granularity period for the PM report in seconds",
+          "type": "number"
+        },
+        "measInfoList": {
+          "description": "array of measurements",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/measInfo"
+          }
+        },
+        "measObjInstIdList": {
+          "description": "array of monitored object local distinguished name ids per 3GPP TS 32.300",
+          "type": "array",
+          "items": {
+            "type": "string"
+          }
+        },
+        "measuredEntityDn": {
+          "description": "distinguished name per 3GPP TS 28.550",
+          "type": "string"
+        },
+        "measuredEntitySoftwareVersion": {
+          "description": "software version for the NF providing the PM data as specified in 3GPP TS 28.550",
+          "type": "string"
+        },
+        "measuredEntityUserName": {
+          "description": "user definable name for the measured object per 3GPP TS 28.550",
+          "type": "string"
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "granularityPeriod",
+        "measInfoList",
+        "measuredEntityDn"
+      ]
+    },
+    "measInfo": {
+      "description": "measurement information.",
+      "type": "object",
+      "properties": {
+        "jobId": {
+          "description": "name of the measurement job",
+          "type": "string"
+        },
+        "measInfoId": {
+          "description": "measurement group identifier",
+          "oneOf": [
+            {
+              "$ref": "#/definitions/measInfoIdInteger"
+            },
+            {
+              "$ref": "#/definitions/measInfoIdString"
+            }
+          ]
+        },
+        "measTypes": {
+          "oneOf": [
+            {
+              "$ref": "#/definitions/measTypesInteger"
+            },
+            {
+              "$ref": "#/definitions/measTypesString"
+            }
+          ]
+        },
+        "measValuesList": {
+          "description": "an array of measurement values",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/measValues"
+          }
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "measTypes",
+        "measValuesList"
+      ]
+    },
+    "measInfoIdInteger": {
+      "description": "integer measurement group identifier",
+      "type": "object",
+      "properties": {
+        "iMeasInfoId": {
+          "type": "integer"
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "iMeasInfoId"
+      ]
+    },
+    "measInfoIdString": {
+      "description": "string measurement group identifier",
+      "type": "object",
+      "properties": {
+        "sMeasInfoId": {
+          "type": "string"
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "sMeasInfoId"
+      ]
+    },
+    "measResultInteger": {
+      "description": "integer 3GPP PM measurement result",
+      "type": "object",
+      "properties": {
+        "p": {
+          "description": "integer reference to the counter",
+          "type": "integer"
+        },
+        "iValue": {
+          "description": "integer counter value",
+          "type": "integer"
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "p",
+        "iValue"
+      ]
+    },
+    "measResultNull": {
+      "description": "null 3GPP PM measurement result",
+      "type": "object",
+      "properties": {
+        "p": {
+          "description": "integer reference to the counter",
+          "type": "integer"
+        },
+        "isNull": {
+          "description": "true if the counter has no value",
+          "type": "string",
+          "enum": [
+            "true",
+            "false"
+          ]
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "p",
+        "isNull"
+      ]
+    },
+    "measResultNumber": {
+      "description": "number 3GPP PM measurement result",
+      "type": "object",
+      "properties": {
+        "p": {
+          "description": "integer reference to the counter",
+          "type": "integer"
+        },
+        "rValue": {
+          "description": "numeric counter value",
+          "type": "number"
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "p",
+        "rValue"
+      ]
+    },
+    "measResultString": {
+      "description": "string 3GPP PM measurement result",
+      "type": "object",
+      "properties": {
+        "p": {
+          "description": "integer reference to the counter",
+          "type": "integer"
+        },
+        "sValue": {
+          "description": "string counter value",
+          "type": "string"
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "p",
+        "sValue"
+      ]
+    },
+    "measTypesInteger": {
+      "description": "object containing an array of integer measurement identifiers associated with the measurement results",
+      "type": "object",
+      "properties": {
+        "iMeasTypesList": {
+          "type": "array",
+          "items": {
+            "type": "integer"
+          }
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "iMeasTypesList"
+      ]
+    },
+    "measTypesString": {
+      "description": "object containing an array of string measurement identifiers associated with the measurement results",
+      "type": "object",
+      "properties": {
+        "sMeasTypesList": {
+          "type": "array",
+          "items": {
+            "type": "string"
+          }
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "sMeasTypesList"
+      ]
+    },
+    "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"
+      ]
+    },
+    "measValues": {
+      "description": "3GPP measurement values",
+      "type": "object",
+      "properties": {
+        "measObjAddlFlds": {
+          "$ref": "#/definitions/hashMap"
+        },
+        "measObjInstId": {
+          "description": "monitored object local distinguished name per 3GPP TS 32.300 and 3GPP TS 32.432",
+          "type": "string"
+        },
+        "measResults": {
+          "description": "array of results",
+          "type": "array",
+          "items": {
+            "oneOf": [
+              {
+                "$ref": "#/definitions/measResultInteger"
+              },
+              {
+                "$ref": "#/definitions/measResultNull"
+              },
+              {
+                "$ref": "#/definitions/measResultNumber"
+              },
+              {
+                "$ref": "#/definitions/measResultString"
+              }
+            ]
+          }
+        },
+        "suspectFlag": {
+          "description": "indicates if the values are suspect",
+          "type": "string",
+          "enum": [
+            "true",
+            "false"
+          ]
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "measObjInstId",
+        "measResults"
+      ]
+    },
+    "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"
+      ]
+    },
+    "perf3gppFields": {
+      "description": "fields for 3GPP PM format events, based on 3GPP TS 28.550, belonging to the 'perf3gpp' domain of the commonEventHeader domain enumeration",
+      "type": "object",
+      "properties": {
+        "eventAddlFields": {
+          "$ref": "#/definitions/hashMap"
+        },
+        "measDataCollection": {
+          "$ref": "#/definitions/measDataCollection"
+        },
+        "perf3gppFieldsVersion": {
+          "description": "version of the perf3gppFields block",
+          "type": "string",
+          "enum": [
+            "1.0",
+            "1.0.1"
+          ]
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "measDataCollection",
+        "perf3gppFieldsVersion"
+      ]
+    },
+    "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 <variables> 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"
+      ]
+    }
+  }
+}
+
index 80e90ed..4a4a079 100644 (file)
@@ -17,9 +17,9 @@ Suite Teardown    Run keywords  VES Collector Suite Shutdown DMaaP  Remove Certs
 #No authentication tests
 
 VES Collector HTTP Health Check
-    [Tags]    DCAE-VESC-R1
-    [Documentation]   Run healthcheck
-    Run Healthcheck
+    [Tags]    DCAE-VESC-R1  DCAE-VESC-HC
+    [Documentation]   Run healthcheck over HTTP
+    Run Healthcheck  ${http_session}
 
 Publish Single VES VNF Measurement Event API V7
     [Tags]    DCAE-VESC-R1
@@ -94,9 +94,9 @@ Publish VES Event With Invalid URL Path
     Log   Send HTTP Request with invalid /listener/v5/ instead of /eventListener/v5 path
     Send Request And Validate Response  Publish Event To VES Collector  ${http_session}  /listener/v5/  ${EVENT_DATA_FILE}  404
 
-Publish PNF Registration Event
+Publish 'Other' Registration Event
     [Tags]    DCAE-VESC-R1
-    [Documentation]   Post PNF registration event and expect 200 Response Status Code
+    [Documentation]   Post an event aligned with “other” domain and expect HTTP 202 Accepeted Response Status Code
     Send Request And Validate Response  Publish Event To VES Collector  ${http_session}  ${VES_ANY_EVENT_PATH}  ${EVENT_PNF_REGISTRATION}  202  QTFCOC540002E-reg
 
 Publish VES Event With Invalid Method V7
@@ -111,21 +111,27 @@ Publish VES Event With Invalid URL Path V7
     Log   Send HTTP Request with invalid /listener/v5/ instead of /eventListener/v5 path
     Send Request And Validate Response  Publish Event To VES Collector  ${http_session}  /listener/v7/  ${EVENT_DATA_FILE}  404
 
-Publish PNF Registration Event V7
+Publish PNF Registration Event
     [Tags]    DCAE-VESC-R1
-    [Documentation]   Post PNF registration event and expect 200 Response Status Code
+    [Documentation]   Post PNF Registration event and expect HTTP 202 Accepeted Response Status Code
     Send Request And Validate Response  Publish Event To VES Collector  ${http_session}  ${VES_EVENTLISTENER_V7}  ${EVENT_PNF_REGISTRATION_V7}  202  registration_38407540
 
 # Auth by certificate and basic auth username / password
 
 Enable VESC HTTPS with certBasicAuth
-    [Tags]    DCAE-VESC-R1
+    [Tags]    DCAE-VESC-R1  DCAE-VESC-HC
     [Documentation]  Enable VESC Https and Authentication and Run Health Check
     Enable VESC with certBasicAuth
-    Run Healthcheck
+    Run Healthcheck  ${https_basic_auth_session}
+
+VES Collector HTTP Health Check with certBasicAuth
+    [Tags]    DCAE-VESC-R1  DCAE-VESC-HC
+    [Documentation]   Run healthcheck over HTTP with certBasicAuth
+    Enable VESC with certBasicAuth
+    Run Healthcheck  ${http_session}
 
 Healthcheck with Outdated Cert
-    [Tags]    DCAE-VESC-R1
+    [Tags]    DCAE-VESC-R1  DCAE-VESC-HC
     [Documentation]  Run healthcheck with outdated cert
     ${uuid}=    Generate UUID
     ${headers}=  Create Dictionary     Accept=*/*     X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid}    X-FromAppId=${GLOBAL_APPLICATION_ID}
index 779397e..500afd5 100644 (file)
@@ -119,7 +119,7 @@ class DMaaPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
             global EvtSchema
             try:
                 if EvtSchema is None:
-                    with open(DcaeVariables.CommonEventSchemaV5) as opened_file:
+                    with open(DcaeVariables.CommonEventSchema) as opened_file:
                         EvtSchema = json.load(opened_file)
                 decoded_body = json.loads(post_body)
                 jsonschema.validate(decoded_body, EvtSchema)
@@ -368,8 +368,8 @@ class DMaaPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
 
 
 def test(handler_class=DMaaPHandler, server_class=BaseHTTPServer.HTTPServer, protocol="HTTP/1.0", port=3904):
-    print "Load event schema file: " + DcaeVariables.CommonEventSchemaV5
-    with open(DcaeVariables.CommonEventSchemaV5) as opened_file:
+    print "Load event schema file: " + DcaeVariables.CommonEventSchema
+    with open(DcaeVariables.CommonEventSchema) as opened_file:
         global EvtSchema
         EvtSchema = json.load(opened_file)
         
@@ -394,8 +394,8 @@ def _main_(handler_class=DMaaPHandler, server_class=BaseHTTPServer.HTTPServer, p
     else:
         port = 3904
     
-    print "Load event schema file: " + DcaeVariables.CommonEventSchemaV5
-    with open(DcaeVariables.CommonEventSchemaV5) as opened_file:
+    print "Load event schema file: " + DcaeVariables.CommonEventSchema
+    with open(DcaeVariables.CommonEventSchema) as opened_file:
         global EvtSchema
         EvtSchema = json.load(opened_file)
         
index ac1eb9f..84d06ae 100644 (file)
@@ -8,7 +8,7 @@ def get_environment_variable(env_varstr):
 DCAE_HEALTH_CHECK_URL = "http://135.205.228.129:8500"
 DCAE_HEALTH_CHECK_URL1 = "http://135.205.228.170:8500"
 
-CommonEventSchemaV5 = get_environment_variable('WORKSPACE') + "/tests/dcaegen2/testcases/assets/json_events/CommonEventFormat_28.3.json"
+CommonEventSchema = get_environment_variable('WORKSPACE') + "/tests/dcaegen2/testcases/assets/json_events/CommonEventFormat_30.1.1.json"
 
 HttpServerThread = None
 HTTPD = None
index 0011ab8..89a8786 100644 (file)
@@ -167,7 +167,8 @@ Send Request And Expect Error
 
 Run Healthcheck
     [Documentation]  Run Healthcheck
+    [Arguments]  ${session}
     ${uuid}=    Generate UUID
     ${headers}=  Create Dictionary     Accept=*/*     X-TransactionId=${GLOBAL_APPLICATION_ID}-${uuid}    X-FromAppId=${GLOBAL_APPLICATION_ID}
-    ${resp}=   Get Request     ${http_session}         /healthcheck        headers=${headers}
+    ${resp}=   Get Request     ${session}      /healthcheck        headers=${headers}
     Should Be Equal As Strings         ${resp.status_code}     200
index c3921d5..79a5750 100644 (file)
@@ -33,14 +33,14 @@ SendPlacementWithValidAuth
     Should Be Equal As Integers    ${resp.status_code}    202
     Should Be Equal     accepted    ${response_json['requestStatus']}
 
-#SendPCIOptimizationWithAuth
-#    [Documentation]    It sends a POST request PCI Optimization service
-#
-#    ${data}=         Get Binary File     ${CURDIR}${/}data${/}pci-opt-request.json
-#    ${resp}=         Http Post        host=${osdf_host}   restUrl=/api/oof/v1/pci     data=${data}    auth=${pci_auth}
-#    ${response_json}    json.loads    ${resp.content}
-#    Should Be Equal As Integers    ${resp.status_code}    202
-#    Should Be Equal     accepted    ${response_json['requestStatus']}
+SendPCIOptimizationWithAuth
+    [Documentation]    It sends a POST request PCI Optimization service
+
+    ${data}=         Get Binary File     ${CURDIR}${/}data${/}pci-opt-request.json
+    ${resp}=         Http Post        host=${osdf_host}   restUrl=/api/oof/v1/pci     data=${data}    auth=${pci_auth}
+    ${response_json}    json.loads    ${resp.content}
+    Should Be Equal As Integers    ${resp.status_code}    202
+    Should Be Equal     accepted    ${response_json['requestStatus']}
 
 
 
index 0a41a6c..c3586cf 100644 (file)
@@ -38,14 +38,3 @@ Frankfurt
      Should Be Equal As Strings    ${resp.status_code}     200
      Should Be Equal As Strings    ${resp.json()['frankfurt']}  0
 
-Usecases
-     [Documentation]    Checks usecases controller is up
-     ${auth}=    Create List    demo@people.osaaf.org    demo123456!
-     Log    Creating session https://${POLICY_DROOLS_IP}:9696
-     ${session}=    Create Session      policy  https://${POLICY_DROOLS_IP}:9696   auth=${auth}
-     ${headers}=  Create Dictionary     Accept=application/json    Content-Type=application/json
-     ${resp}=   Get Request     policy  /policy/pdp/engine/controllers/usecases/drools/facts     headers=${headers}
-     Log    Received response from policy ${resp.text}
-     Should Be Equal As Strings    ${resp.status_code}     200
-     Should Be Equal As Strings    ${resp.json()['usecases']}  0
-
index 36b593c..67a5782 100644 (file)
@@ -5,6 +5,17 @@ Library     OperatingSystem
 Library     json
 
 *** Test Cases ***
+LoadPolicy
+     [Documentation]    Loads prerequisite Policy via API
+     ${auth}=    Create List    healthcheck    zb!XztG34
+     Log    Creating session https://${POLICY_API_IP}:6969
+     ${session}=    Create Session      policy  https://${POLICY_API_IP}:6969   auth=${auth}
+     ${headers}=  Create Dictionary     Accept=application/json    Content-Type=application/json
+     ${postjson}=  Get file  ${CURDIR}/data/vCPE.policy.monitoring.input.tosca.json
+     ${resp}=   Post Request     policy  /policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/policies    data=${postjson}     headers=${headers}
+     Log    Received response from API ${resp.text}
+     Should Be Equal As Strings    ${resp.status_code}     200
+
 Healthcheck
      [Documentation]    Runs Policy PAP Health check
      ${auth}=    Create List    healthcheck    zb!XztG34
index 1941e35..49e4faa 100644 (file)
@@ -3,7 +3,7 @@ Resource          sdc_interface.robot
 Resource          sdc_dcaed_interface.robot
 
 *** Test Cases ***
-# This test case implements the steps described in
+# For now, this test case implements the steps described in
 # https://wiki.onap.org/display/DW/How+to+Create+a+Service+with+a+Monitoring+Configuration+using+SDC
 Create Service With Monitoring Configuration Test
     [Tags]  sdc-dcae-d
diff --git a/tests/usecases/pnf-sw-upgrade/.gitignore b/tests/usecases/pnf-sw-upgrade/.gitignore
new file mode 100755 (executable)
index 0000000..44793d7
--- /dev/null
@@ -0,0 +1,22 @@
+target
+**/.settings
+**/.classpath
+**/.project
+**/.buildpath
+**/.factorypath
+**/.springBeans
+.idea
+.checkstyle
+.DS_Store
+.*~
+*.iml
+*.class
+*.swp
+*.log
+*.tmp
+**/bin/
+/.metadata/
+temp/
+**/temp/**
+test_lab/
+**/test_lab/**
diff --git a/tests/usecases/pnf-sw-upgrade/__init__.robot b/tests/usecases/pnf-sw-upgrade/__init__.robot
new file mode 100644 (file)
index 0000000..a721a88
--- /dev/null
@@ -0,0 +1,2 @@
+1 *** Settings ***
+2 Documentation    PNF - pnf-sw-upgrade
diff --git a/tests/usecases/pnf-sw-upgrade/data/blueprint_archive.zip b/tests/usecases/pnf-sw-upgrade/data/blueprint_archive.zip
new file mode 100644 (file)
index 0000000..4edc9de
Binary files /dev/null and b/tests/usecases/pnf-sw-upgrade/data/blueprint_archive.zip differ
diff --git a/tests/usecases/pnf-sw-upgrade/data/distributeServiceTemplate.json b/tests/usecases/pnf-sw-upgrade/data/distributeServiceTemplate.json
new file mode 100644 (file)
index 0000000..c13eb8d
--- /dev/null
@@ -0,0 +1,35 @@
+{                                                                                          
+    "distributionID": "05fd08d8-c452-429a-a1ad-806c8d05e7c8",                                                                                                                                   
+    "serviceName": "Demo_svc",                                                                                                                                                                  
+    "serviceVersion": "1.0",                                                                                                                                                                    
+    "serviceUUID": "cd4decf6-4f27-4775-9561-0e683ed43635",                                                                                                                                      
+    "serviceDescription": "aaaa",                                                                                                                                                               
+    "serviceInvariantUUID": "fe41489e-1563-46a3-b90a-1db629e4375b",                                                                                                                             
+    "resources": [                                                                                                                                                                              
+      {                                                                                                                                                                                         
+        "resourceInstanceName": "Demo_pnf 0",                                                                                                                                                   
+        "resourceCustomizationUUID": "36b46817-2eaf-41b3-bfa3-11a7e0fd9bb2",                                                                                                                    
+        "resourceName": "Demo_pnf",                                                                                                                                                             
+        "resourceVersion": "1.0",                                                                                                                                                               
+        "resoucreType": "PNF",                                                                                                                                                                  
+        "resourceUUID": "a42f6566-6a29-43e1-bac9-b91a59d702ac",                                                                                                                                 
+        "resourceInvariantUUID": "fdf44827-35db-4ee5-bd70-7500e633576e",                                                                                                                        
+        "category": "Network L4+",                                                                                                                                                              
+        "subcategory": "Common Network Resources",                                                                                                                                              
+        "artifacts": []                                                                                                                                                                         
+      }                                                                                                                                                                                         
+    ],                                                                                                                                                                                          
+    "serviceArtifacts": [                                                                                                                                                                       
+      {                                                                                                                                                                                         
+        "artifactName": "service-DemoSvc-csar.csar",                                                                                                                                            
+        "artifactType": "TOSCA_CSAR",                                                                                                                                                           
+        "artifactURL": "//unzipped_sdc_csar/v1/catalog/services/DemoSvc/1.0/artifacts/service-DemoSvc-csar.csar",                                                                                              
+        "artifactChecksum": "Njk4NDM4YTdjYmM4NWFkN2M1YWZiM2IzYzdmNWZjZTU\u003d",                                                                                                                
+        "artifactDescription": "TOSCA definition package of the asset",                                                                                                                         
+        "artifactTimeout": 0,                                                                                                                                                                   
+        "artifactVersion": "1",                                                                                                                                                                 
+        "artifactUUID": "e2640671-a5ed-40a6-b231-8f33084b1c1a"                                                                                                                                  
+      }                                                                                                                                                                                         
+    ],                                                                                                                                                                                          
+    "workloadContext": "Production"                                                                                                                                                             
+  }                                                                 
\ No newline at end of file
diff --git a/tests/usecases/pnf-sw-upgrade/data/mount.json b/tests/usecases/pnf-sw-upgrade/data/mount.json
new file mode 100755 (executable)
index 0000000..58925b1
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "node": [
+    {
+      "node-id": "PNFDemo",
+      "netconf-node-topology:protocol": {
+        "name": "TLS"
+      },
+      "netconf-node-topology:host": "pnfaddr",
+      "netconf-node-topology:key-based": {
+        "username": "netconf",
+        "key-id": "ODL_private_key_0"
+      },
+      "netconf-node-topology:port": 6513,
+      "netconf-node-topology:tcp-only": false,
+      "netconf-node-topology:max-connection-attempts": 5
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/usecases/pnf-sw-upgrade/data/serviceInstantiationActivationRequest.json b/tests/usecases/pnf-sw-upgrade/data/serviceInstantiationActivationRequest.json
new file mode 100644 (file)
index 0000000..a25ebfd
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    "requestDetails":{
+      "requestInfo":{
+        "source":"VID",
+        "suppressRollback":false,
+        "requestorId":"demo"
+      },
+      "modelInfo":{
+        "modelType":"service",
+        "modelInvariantUuid":"fe41489e-1563-46a3-b90a-1db629e4375b",
+        "modelInvariantId" : "fe41489e-1563-46a3-b90a-1db629e4375b",
+        "modelUuid":"cd4decf6-4f27-4775-9561-0e683ed43635",
+        "modelVersionId" : "cd4decf6-4f27-4775-9561-0e683ed43635",
+        "modelName":"Demo_svc",
+        "modelVersion":"1.0"
+      },
+      "requestParameters":{
+        "userParams":[
+          {
+            "name":"targetSoftwareVersion",
+            "value":"pnf_sw_version-3.0.0"
+          },
+          {
+            "name":"pnfName",
+            "value":"PNFDemo"
+          }
+        ],
+        "subscriptionServiceType":"vCPE",
+        "aLaCarte":false
+   
+      },
+      "subscriberInfo": {
+              "globalSubscriberId": "DemoCustomer"
+          },
+     "project": {
+              "projectName": "pnfSWUProject"
+          },
+      "owningEntity": {
+          "owningEntityId": "f2e1071e-3d47-4a65-94d4-e473ec03326a",
+          "owningEntityName": "OE-Demonstration"
+          }
+    }
+  }
\ No newline at end of file
diff --git a/tests/usecases/pnf-sw-upgrade/data/serviceInstantiationDownloadRequest.json b/tests/usecases/pnf-sw-upgrade/data/serviceInstantiationDownloadRequest.json
new file mode 100644 (file)
index 0000000..0042ac2
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    "requestDetails":{
+      "requestInfo":{
+        "source":"VID",
+        "suppressRollback":false,
+        "requestorId":"demo"
+      },
+      "modelInfo":{
+        "modelType":"service",
+        "modelInvariantUuid":"fe41489e-1563-46a3-b90a-1db629e4375b",
+        "modelInvariantId" : "fe41489e-1563-46a3-b90a-1db629e4375b",
+        "modelUuid":"cd4decf6-4f27-4775-9561-0e683ed43635",
+        "modelVersionId" : "cd4decf6-4f27-4775-9561-0e683ed43635",
+        "modelName":"Demo_svc",
+        "modelVersion":"1.0"
+      },
+      "requestParameters":{
+        "userParams":[
+          {
+            "name":"targetSoftwareVersion",
+            "value":"pnf_sw_version-2.0.0"
+          },
+          {
+            "name":"pnfName",
+            "value":"PNFDemo"
+          }
+        ],
+        "subscriptionServiceType":"vCPE",
+        "aLaCarte":false
+   
+      },
+      "subscriberInfo": {
+              "globalSubscriberId": "DemoCustomer"
+          },
+     "project": {
+              "projectName": "pnfSWUProject"
+          },
+      "owningEntity": {
+          "owningEntityId": "f2e1071e-3d47-4a65-94d4-e473ec03326a",
+          "owningEntityName": "OE-Demonstration"
+          }
+    }
+  }
\ No newline at end of file
diff --git a/tests/usecases/pnf-sw-upgrade/pnf-sw-upgrade.robot b/tests/usecases/pnf-sw-upgrade/pnf-sw-upgrade.robot
new file mode 100644 (file)
index 0000000..7040836
--- /dev/null
@@ -0,0 +1,202 @@
+*** Settings ***
+Library     Collections
+Library     RequestsLibrary
+Library     OperatingSystem
+Library     json
+Library     String
+
+*** Variables ***
+${SDNC_KEYSTORE_CONFIG_PATH}    /restconf/config/netconf-keystore:keystore
+${SDNC_MOUNT_PATH}    /restconf/config/network-topology:network-topology/topology/topology-netconf/node/PNFDemo
+${PNFSIM_MOUNT_PATH}    /restconf/config/network-topology:network-topology/topology/topology-netconf/node/PNFDemo/yang-ext:mount/pnf-sw-upgrade:software-upgrade
+${PNFSIM_DELETE_PATH}    /restconf/config/network-topology:network-topology/topology/topology-netconf/node/PNFDemo
+${BP_UPLOAD_URL}    /api/v1/blueprint-model/publish
+${BP_PROCESS_URL}    /api/v1/execution-service/process
+${BP_ARCHIVE_PATH}    ${CURDIR}/data/blueprint_archive.zip
+${SLEEP_INTERVAL_SEC}=   5
+${MAXIMUM_ATTEMPTS_BEFORE_TIMEOUT}=     20   
+
+
+*** Test Cases ***
+Test SDNC Keystore
+      [Documentation]    Checking keystore after SDNC installation
+      Create Session   sdnc  http://${REPO_IP}:8282
+      &{headers}=  Create Dictionary    Authorization=Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==    Content-Type=application/json    Accept=application/json
+      ${resp}=    Get Request    sdnc    ${SDNC_KEYSTORE_CONFIG_PATH}    headers=${headers}
+      Should Be Equal As Strings    ${resp.status_code}    200
+      ${keystoreContent}=    Convert To String    ${resp.content}
+      Log to console  *************************
+      Log to console  ${resp.content}
+      Log to console  *************************
+
+Test BP-PROC upload blueprint archive
+     [Documentation]    Upload Blueprint archive to BP processor
+     Create Session   blueprint  http://${REPO_IP}:8000
+     ${bp_archive}=    Get Binary File    ${BP_ARCHIVE_PATH}
+     &{bp_file}=    create Dictionary    file    ${bp_archive} 
+     &{headers}=  Create Dictionary    Authorization=Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==
+     ${resp}=    Post Request    blueprint    ${BP_UPLOAD_URL}    files=${bp_file}    headers=${headers}
+     Should Be Equal As Strings    ${resp.status_code}    200
+
+Distribute Service Template
+    Create Session   sdc_controller_session  http://${REPO_IP}:8085
+    ${data}=    Get Binary File     ${CURDIR}${/}data${/}distributeServiceTemplate.json
+    &{headers}=  Create Dictionary    Authorization=Basic bXNvX2FkbWluOnBhc3N3b3JkMSQ=    resource-location=/app/distribution-test-zip/unzipped/    Content-Type=application/json    Accept=application/json
+    ${resp}=    Post Request    sdc_controller_session    /test/treatNotification/v1    data=${data}    headers=${headers}
+    Run Keyword If  '${resp.status_code}' == '200'  log to console  \nexecuted with expected result
+    Should Be Equal As Strings    '${resp.status_code}'    '200'
+    ${serviceInstanceId}=    Set Variable    cd4decf6-4f27-4775-9561-0e683ed43635
+    SET GLOBAL VARIABLE     ${serviceInstanceId}
+    ${pnfName}=    Set Variable    PNFDemo
+    SET GLOBAL VARIABLE       ${pnfName}
+
+Get pnf workflow
+    Create Session   api_handler_session  http://${REPO_IP}:8080
+    &{headers}=  Create Dictionary    Authorization=Basic SW5mcmFQb3J0YWxDbGllbnQ6cGFzc3dvcmQxJA==    Content-Type=application/json    Accept=application/json
+    ${get_pnfworkflows_request}=    Get Request    api_handler_session    /onap/so/infra/workflowSpecifications/v1/pnfWorkflows     headers=${headers}
+    Run Keyword If  '${get_pnfworkflows_request.status_code}' == '200'  log to console   \nexecuted with expected result
+    log to console      ${get_pnfworkflows_request.content}
+    ${pnfworkflows_json_response}=    Evaluate     json.loads(r"""${get_pnfworkflows_request.content}""", strict=False)    json
+    ${all_wf_members}=    Set Variable     ${pnfworkflows_json_response['workflowSpecificationList']}
+    ${activate_workflow_uuid}=    Set Variable    ""
+    ${activate_workflow_name}=    Set Variable    ""
+    ${download_workflow_uuid}=    Set Variable    ""
+    ${download_workflow_name}=    Set Variable    ""
+
+    :FOR    ${member}     IN      @{all_wf_members}
+    \   ${workflow_uuid}=          Set Variable        ${member}[workflowSpecification][artifactInfo][artifactUuid]
+    \   ${workflow_name}=          Set Variable        ${member}[workflowSpecification][artifactInfo][artifactName]
+    \   Log to console   The workflow ${workflow_name} has uuid : ${workflow_uuid}
+    \   ${activate_workflow_uuid}=    Set Variable If  '${workflow_name}' == 'PNFSoftwareUpgrade'    ${workflow_uuid}   ${activate_workflow_uuid} 
+    \   ${activate_workflow_name}=    Set Variable If  '${workflow_name}' == 'PNFSoftwareUpgrade'    ${workflow_name}   ${activate_workflow_name}
+    \   ${download_workflow_uuid}=    Set Variable If  '${workflow_name}' == 'PNFSWUPDownload'       ${workflow_uuid}   ${download_workflow_uuid}
+    \   ${download_workflow_name}=    Set Variable If  '${workflow_name}' == 'PNFSWUPDownload'       ${workflow_name}   ${download_workflow_name}
+    
+    SET GLOBAL VARIABLE       ${activate_workflow_uuid}
+    SET GLOBAL VARIABLE       ${download_workflow_uuid}
+
+    Run Keyword If  '${activate_workflow_name}' == 'PNFSoftwareUpgrade'  log to console   \nexecuted with expected result
+    Run Keyword If  '${download_workflow_name}' == 'PNFSWUPDownload'  log to console   \nexecuted with expected result
+    Should Be Equal As Strings    '${activate_workflow_name}'    'PNFSoftwareUpgrade'
+    Should Be Equal As Strings    '${download_workflow_name}'    'PNFSWUPDownload'
+
+Invoke Service Instantiation for pnf software download
+    Create Session   api_handler_session  http://${REPO_IP}:8080
+    ${data}=    Get Binary File     ${CURDIR}${/}data${/}serviceInstantiationDownloadRequest.json
+    &{headers}=  Create Dictionary    Authorization=Basic SW5mcmFQb3J0YWxDbGllbnQ6cGFzc3dvcmQxJA==    Content-Type=application/json    Accept=application/json    X-ONAP-RequestID=0ddc448d-5513-44bc-8b02-5759d84600d5    X-ONAP-PartnerName=ONAP    X-RequestorID=VID
+    ${service_instantiation_request}=    Post Request    api_handler_session    /onap/so/infra/instanceManagement/v1/serviceInstances/${serviceInstanceId}/pnfs/${pnfName}/workflows/${download_workflow_uuid}    data=${data}    headers=${headers}
+    Run Keyword If  '${service_instantiation_request.status_code}' == '200'  log to console   \nexecuted with expected result
+    log to console      ${service_instantiation_request.content}
+    ${service_instantiation_json_response}=    Evaluate     json.loads(r"""${service_instantiation_request.content}""", strict=False)    json
+    ${request_ID}=          Set Variable         ${service_instantiation_json_response}[requestReferences][requestId]
+    ${actual_request_state}=    Set Variable    ""
+
+    : FOR    ${INDEX}    IN RANGE    ${MAXIMUM_ATTEMPTS_BEFORE_TIMEOUT}
+    \   ${orchestration_status_request}=   Get Request  api_handler_session   /onap/so/infra/orchestrationRequests/v7/${request_ID}
+    \   Run Keyword If  '${orchestration_status_request.status_code}' == '200'  log to console   \nexecuted with expected result
+    \   log to console      ${orchestration_status_request.content}
+    \   ${orchestration_json_response}=    Evaluate     json.loads(r"""${orchestration_status_request.content}""", strict=False)    json
+    \   ${actual_request_state}=     SET VARIABLE       ${orchestration_json_response}[request][requestStatus][requestState]
+    \   Log To Console    Received actual repsonse status:${actual_request_state}
+    \   RUN KEYWORD IF   '${actual_request_state}' == 'COMPLETED' or '${actual_request_state}' == 'FAILED'      Exit For Loop
+    \   log to console  Will try again after ${SLEEP_INTERVAL_SEC} seconds
+    \   SLEEP   ${SLEEP_INTERVAL_SEC}s
+
+    Log To Console     final repsonse status received: ${actual_request_state}
+    Run Keyword If  '${actual_request_state}' == 'COMPLETED'  log to console   \nexecuted with expected result
+    Should Be Equal As Strings    '${actual_request_state}'    'COMPLETED'
+
+Test verify PNF Configuration for software download
+     [Documentation]    Checking PNF configuration params
+
+     Create Session   sdnc  http://${REPO_IP}:8282
+     &{headers}=  Create Dictionary    Authorization=Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==    Content-Type=application/json
+     ${mount}=    Get File     ${CURDIR}${/}data${/}mount.json
+     Log to console  ${mount}
+     ${pnf_mount_resp}=    Put Request    sdnc    ${SDNC_MOUNT_PATH}    data=${mount}    headers=${headers}
+     Should Be Equal As Strings    ${pnf_mount_resp.status_code}    201
+     SLEEP   10
+     ${pnfsim_software_resp}=    Get Request    sdnc    ${PNFSIM_MOUNT_PATH}    headers=${headers}
+     Should Be Equal As Strings    ${pnfsim_software_resp.status_code}    200
+     Log to console  ${pnfsim_software_resp.content}
+     ${pnfsim_software_resp_json}=    Evaluate     json.loads(r"""${pnfsim_software_resp.content}""", strict=False)    json
+     ${all_upgp_members}=    Set Variable     ${pnfsim_software_resp_json['software-upgrade']['upgrade-package']}
+
+     :FOR    ${member}     IN      @{all_upgp_members}
+     \   ${soft_ver}=    Get From Dictionary   ${member}     software-version
+     \   ${soft_status}=    Get From Dictionary   ${member}     current-status
+     \   Log to console   The node ${pnfName} has software version ${soft_ver} : ${soft_status}
+     \   Run Keyword If  '${soft_ver}' == 'pnf_sw_version-2.0.0'   Exit For Loop
+
+     Run Keyword If  '${soft_ver}' == 'pnf_sw_version-2.0.0'  log to console   \nexecuted with expected result
+     Should Be Equal As Strings    '${soft_ver}'    'pnf_sw_version-2.0.0'
+     Should Be Equal As Strings    '${soft_status}'    'DOWNLOAD_COMPLETED'
+
+Invoke Service Instantiation for pnf software activation
+    Create Session   api_handler_session  http://${REPO_IP}:8080
+    ${data}=    Get Binary File     ${CURDIR}${/}data${/}serviceInstantiationActivationRequest.json
+    &{headers}=  Create Dictionary    Authorization=Basic SW5mcmFQb3J0YWxDbGllbnQ6cGFzc3dvcmQxJA==    Content-Type=application/json    Accept=application/json    X-ONAP-RequestID=4e104e12-5539-4557-b31e-00369398c214    X-ONAP-PartnerName=ONAP    X-RequestorID=VID
+    ${service_instantiation_request}=    Post Request    api_handler_session    /onap/so/infra/instanceManagement/v1/serviceInstances/${serviceInstanceId}/pnfs/${pnfName}/workflows/${activate_workflow_uuid}    data=${data}    headers=${headers}
+    Run Keyword If  '${service_instantiation_request.status_code}' == '200'  log to console   \nexecuted with expected result
+    log to console      ${service_instantiation_request.content}
+    ${service_instantiation_json_response}=    Evaluate     json.loads(r"""${service_instantiation_request.content}""", strict=False)    json
+    ${request_ID}=          Set Variable         ${service_instantiation_json_response}[requestReferences][requestId]
+    ${actual_request_state}=    Set Variable    ""
+    : FOR    ${INDEX}    IN RANGE    ${MAXIMUM_ATTEMPTS_BEFORE_TIMEOUT}
+    \   ${orchestration_status_request}=   Get Request  api_handler_session   /onap/so/infra/orchestrationRequests/v7/${request_ID}
+    \   Run Keyword If  '${orchestration_status_request.status_code}' == '200'  log to console   \nexecuted with expected result
+    \   log to console      ${orchestration_status_request.content}
+    \   ${orchestration_json_response}=    Evaluate     json.loads(r"""${orchestration_status_request.content}""", strict=False)    json
+    \   ${actual_request_state}=     SET VARIABLE       ${orchestration_json_response}[request][requestStatus][requestState]
+    \   Log To Console    Received actual repsonse status:${actual_request_state}
+    \   RUN KEYWORD IF   '${actual_request_state}' == 'COMPLETED' or '${actual_request_state}' == 'FAILED'      Exit For Loop
+    \   log to console  Will try again after ${SLEEP_INTERVAL_SEC} seconds
+    \   SLEEP   ${SLEEP_INTERVAL_SEC}s
+
+    Log To Console     final repsonse status received: ${actual_request_state}
+    Run Keyword If  '${actual_request_state}' == 'COMPLETED'  log to console   \nexecuted with expected result
+    Should Be Equal As Strings    '${actual_request_state}'    'COMPLETED'
+    
+Test verify PNF Configuration for software activate 
+     [Documentation]    Checking PNF configuration params
+
+     Create Session   sdnc  http://${REPO_IP}:8282
+     &{headers}=  Create Dictionary    Authorization=Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==    Content-Type=application/json
+     ${mount}=    Get File     ${CURDIR}${/}data${/}mount.json
+     Log to console  ${mount}
+     ${pnf_mount_resp}=    Put Request    sdnc    ${SDNC_MOUNT_PATH}    data=${mount}    headers=${headers}
+     Should Be Equal As Strings    ${pnf_mount_resp.status_code}    201
+     SLEEP   10
+     ${pnfsim_software_resp}=    Get Request    sdnc    ${PNFSIM_MOUNT_PATH}    headers=${headers}
+     Should Be Equal As Strings    ${pnfsim_software_resp.status_code}    200
+     Log to console  ${pnfsim_software_resp.content}
+     ${pnfsim_software_resp_json}=    Evaluate     json.loads(r"""${pnfsim_software_resp.content}""", strict=False)    json
+     ${all_upgp_members}=    Set Variable     ${pnfsim_software_resp_json['software-upgrade']['upgrade-package']}
+
+     :FOR    ${member}     IN      @{all_upgp_members}
+     \   ${soft_ver}=    Get From Dictionary   ${member}     software-version
+     \   ${soft_status}=    Get From Dictionary   ${member}     current-status
+     \   Log to console   The node ${pnfName} has software version ${soft_ver} : ${soft_status}
+     \   Run Keyword If  '${soft_ver}' == 'pnf_sw_version-3.0.0'   Exit For Loop
+
+     Run Keyword If  '${soft_ver}' == 'pnf_sw_version-3.0.0'  log to console   \nexecuted with expected result
+     Should Be Equal As Strings    '${soft_ver}'    'pnf_sw_version-3.0.0'
+     Should Be Equal As Strings    '${soft_status}'    'ACTIVATION_COMPLETED'
+
+Test AAI-update for target software version verify
+    Create Session   aai_simulator_session  https://${REPO_IP}:9993
+    &{headers}=  Create Dictionary    Authorization=Basic YWFpOmFhaS5vbmFwLm9yZzpkZW1vMTIzNDU2IQ==    Content-Type=application/json    Accept=application/json    verify=False
+    : FOR    ${INDEX}    IN RANGE    ${MAXIMUM_ATTEMPTS_BEFORE_TIMEOUT}
+    \   ${get_pnf_request}=    Get Request    aai_simulator_session    aai/v11/network/pnfs/pnf/${pnfName}     headers=${headers}
+    \   Run Keyword If  '${get_pnf_request.status_code}' == '200'  log to console   \nexecuted with expected result
+    \   ${get_pnf_json_response}=    Evaluate     json.loads(r"""${get_pnf_request.content}""", strict=False)    json
+    \   Log to console  ${get_pnf_json_response}
+    \   ${sw_version}=          Set Variable         ${get_pnf_json_response}[sw-version]
+    \   Log to console  ${sw_version}
+    \   Run Keyword If  '${sw_version}' == 'pnf_sw_version-3.0.0'   Exit For Loop
+    \   log to console  Will try again after ${SLEEP_INTERVAL_SEC} seconds
+    \   SLEEP   ${SLEEP_INTERVAL_SEC}s
+
+    Log To Console     final target software version received: ${sw_version}
+    Run Keyword If  '${sw_version}' == 'pnf_sw_version-3.0.0'  log to console   \nexecuted with expected result
+    Should Be Equal As Strings    '${sw_version}'    'pnf_sw_version-3.0.0'