pnf sw upgrade csit

Change-Id: I776d61030efc3d51e04f98698ceb8c445db2dafa
Signed-off-by: tragait <rahul.tyagi@est.tech>
Issue-ID: INT-1308
Signed-off-by: tragait <rahul.tyagi@est.tech>
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
index 0000000..b6b4610
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/cds/cds_setup.sh
@@ -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
index 0000000..9f2ac53
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/cds/cds_teardown.sh
@@ -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
index 0000000..6fbde12
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/cds/docker-compose.yml
@@ -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
index 0000000..9acb8bb
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/cds/resources/aai.cert
@@ -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
index 0000000..d11bab6
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/cds/resources/application.properties
@@ -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
index 0000000..71196ce
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/cds/resources/error-messages_en.properties
@@ -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
index 0000000..c5501d4
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/cds/resources/importCerAndStartService.sh
@@ -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
index 0000000..f8f3fa7
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/sdn/certs/certs.properties
@@ -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
index 0000000..48b4d90
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/sdn/certs/keys0.zip
Binary files 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
index 0000000..c8a4575
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/sdn/docker-compose.yml
@@ -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
index 0000000..536777a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/sdn/sdn_setup.sh
@@ -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
index 0000000..9f2ac53
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/sdn/sdn_teardown.sh
@@ -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
index 0000000..95d97ca
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/setup.sh
@@ -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
index 0000000..03cad4c
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/docker-compose.yml
@@ -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
index 0000000..3eface2
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/LICENSE
@@ -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
index 0000000..4f1e7bc
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/data.xml
@@ -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
index 0000000..6d41306
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/model.yang
@@ -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
index 0000000..810fe45
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/simulators/pnfsim/pnf-sw-upgrade/subscriber.py
@@ -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
index 0000000..1a16538
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/cloud-esr-system-info.json
@@ -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
index 0000000..fa32840
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/cloud-region.json
@@ -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
index 0000000..6c53c05
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/customer.json
@@ -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
index 0000000..d204a77
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/esr-system-info.json
@@ -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
index 0000000..4d23b43
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/esr-vnfm.json
@@ -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
index 0000000..69f872b
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/line-of-business.json
@@ -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
index 0000000..3bfd9cc
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/owning-entity.json
@@ -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
index 0000000..3265a06
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/platform.json
@@ -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
index 0000000..ab39d8c
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/pnf.json
@@ -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
index 0000000..f67dbc1
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/project.json
@@ -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
index 0000000..746131a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/aai-simulator-populate-data/tenant.json
@@ -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
index 0000000..5833a9e
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/apply-workarounds.sh
@@ -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
index 0000000..9acb8bb
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/certificates/aai-certificate/aai.cert
@@ -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
index 0000000..5af091b
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/distribution-test-zip/zipped_sdc_csar.tar.gz
Binary files 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
index 0000000..77e3dbf
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/env
@@ -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
index 0000000..10a3ec2
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/override-files/api-handler-infra/onapheat/override.yaml
@@ -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
index 0000000..4dd959a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/override-files/bpmn-infra/onapheat/override.yaml
@@ -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
index 0000000..8ab9615
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/override-files/catalog-db-adapter/onapheat/override.yaml
@@ -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
index 0000000..6586116
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/override-files/request-db-adapter/onapheat/override.yaml
@@ -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
index 0000000..ed8bd43
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/override-files/sdc-controller/onapheat/override.yaml
@@ -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
index 0000000..7e61c7d
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/override-files/so-monitoring/onapheat/override.yaml
@@ -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
index 0000000..bb71512
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/override-files/so-vnfm-adapter/onapheat/override.yaml
@@ -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
index 0000000..05cb1e5
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/override-files/vnfm-simulator/onapheat/override.yaml
@@ -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
index 0000000..6852e3f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/populate-aai-simulator.sh
@@ -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
index 0000000..58a0781
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/wait-for-aai-config-job.sh
@@ -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
index 0000000..35ee264
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/wait-for-container.sh
@@ -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
index 0000000..035c5e2
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/wait-for-workaround-job.sh
@@ -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
index 0000000..53581b3
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/config/wait-for.sh
@@ -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
index 0000000..1e56822
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/docker-compose.local.yml
@@ -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
index 0000000..bea0dca
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/docker-compose.yml
@@ -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
index 0000000..5db5298
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/settings.xml
@@ -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
index 0000000..f7c7bc1
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/pom.xml
@@ -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
index 0000000..bb1b190
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/AaiSimulatorApplication.java
@@ -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
index 0000000..109be8a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/configration/ApplicationConfigration.java
@@ -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
index 0000000..1dc483f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/configration/WebSecurityConfigImpl.java
@@ -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
index 0000000..f591290
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/AaiSimulatorController.java
@@ -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
index 0000000..4a0ed1b
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/BusinessController.java
@@ -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
index 0000000..8e007de
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/CloudRegionsController.java
@@ -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
index 0000000..297c2eb
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/ExternalSystemEsrController.java
@@ -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
index 0000000..43fe47d
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/GenericVnfsController.java
@@ -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
index 0000000..b3438d2
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/LinesOfBusinessController.java
@@ -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
index 0000000..21bcae9
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/NodesController.java
@@ -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
index 0000000..c5ade0c
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/OwningEntityController.java
@@ -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
index 0000000..39e3594
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/PlatformController.java
@@ -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
index 0000000..ff0e3dc
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/PnfsController.java
@@ -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
index 0000000..490982a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/controller/ProjectController.java
@@ -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
index 0000000..4a7c289
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/exception/InvalidRestRequestException.java
@@ -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
index 0000000..0a93e2f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/exception/RestProcessingException.java
@@ -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
index 0000000..3c45c19
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/CloudRegionKey.java
@@ -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
index 0000000..1c851fc
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/Format.java
@@ -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
index 0000000..4a64591
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/NodeServiceInstance.java
@@ -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
index 0000000..8dc2024
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/models/Results.java
@@ -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
index 0000000..dd4ace4
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/Clearable.java
@@ -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
index 0000000..6facac8
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CloudRegionCacheServiceProvider.java
@@ -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
index 0000000..f1f782a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CloudRegionCacheServiceProviderImpl.java
@@ -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
index 0000000..7000fb3
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProvider.java
@@ -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
index 0000000..7193ade
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/CustomerCacheServiceProviderImpl.java
@@ -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
index 0000000..b1f9021
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ExternalSystemCacheServiceProvider.java
@@ -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
index 0000000..b5b1da0
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ExternalSystemCacheServiceProviderImpl.java
@@ -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
index 0000000..901c259
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/GenericVnfCacheServiceProvider.java
@@ -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
index 0000000..e7a4210
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/GenericVnfCacheServiceProviderImpl.java
@@ -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
index 0000000..bbcc435
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/HttpRestServiceProvider.java
@@ -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
index 0000000..b96920f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/HttpRestServiceProviderImpl.java
@@ -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
index 0000000..dbf5490
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/LinesOfBusinessCacheServiceProvider.java
@@ -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
index 0000000..7614cb6
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/LinesOfBusinessCacheServiceProviderImpl.java
@@ -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
index 0000000..0232746
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/NodesCacheServiceProvider.java
@@ -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
index 0000000..4ea255f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/NodesCacheServiceProviderImpl.java
@@ -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
index 0000000..394ecf1
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/OwnEntityCacheServiceProvider.java
@@ -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
index 0000000..e351c75
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/OwnEntityCacheServiceProviderImpl.java
@@ -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
index 0000000..65788bc
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PlatformCacheServiceProvider.java
@@ -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
index 0000000..225885c
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PlatformCacheServiceProviderImpl.java
@@ -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
index 0000000..89610e0
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PnfCacheServiceProvider.java
@@ -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
index 0000000..cef6c5a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/PnfCacheServiceProviderImpl.java
@@ -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
index 0000000..9aad53f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ProjectCacheServiceProvider.java
@@ -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
index 0000000..a2eb7ee
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/service/providers/ProjectCacheServiceProviderImpl.java
@@ -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
index 0000000..f38adcc
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/CacheName.java
@@ -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
index 0000000..230dc13
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/Constants.java
@@ -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
index 0000000..8178102
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/HttpServiceUtils.java
@@ -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
index 0000000..782625f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestError.java
@@ -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
index 0000000..f374222
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestErrorBuilder.java
@@ -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
index 0000000..755d3a7
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/RequestErrorResponseUtils.java
@@ -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
index 0000000..7ba47fa
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/ServiceException.java
@@ -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
index 0000000..3285e01
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/java/org/onap/so/aaisimulator/utils/ShallowBeanCopy.java
@@ -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
index 0000000..205abe4
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/application.yaml
@@ -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
index 0000000..015f2bf
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/keystore/org.onap.so.p12
Binary files 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
index 0000000..88d6184
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/main/resources/truststore/org.onap.so.trust.jks
Binary files 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
index 0000000..4fe5c40
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/AaiSimulatorControllerTest.java
@@ -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
index 0000000..84bb8ca
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/AbstractSpringBootTest.java
@@ -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
index 0000000..c08c51e
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/BusinessControllerTest.java
@@ -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
index 0000000..1b96759
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/CloudRegionsControllerTest.java
@@ -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
index 0000000..2fd5f7b
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/ExternalSystemEsrControllerTest.java
@@ -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
index 0000000..8b6ec8c
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/GenericVnfsControllerTest.java
@@ -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
index 0000000..30b3d27
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/LinesOfBusinessControllerTest.java
@@ -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
index 0000000..378d77d
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/NodesControllerTest.java
@@ -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
index 0000000..015994a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/OwningEntityControllerTest.java
@@ -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
index 0000000..7e88eec
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/PlatformControllerTest.java
@@ -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
index 0000000..10e9b66
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/PnfsControllerTest.java
@@ -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
index 0000000..678d417
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/ProjectControllerTest.java
@@ -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
index 0000000..92036e8
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/controller/configuration/TestRestTemplateConfigration.java
@@ -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
index 0000000..85ceeef
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestConstants.java
@@ -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
index 0000000..e49e6d4
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestRestTemplateService.java
@@ -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
index 0000000..55eb0ef
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/java/org/onap/so/aaisimulator/utils/TestUtils.java
@@ -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
index 0000000..6c53c05
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-customer.json
@@ -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
index 0000000..c266226
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-project-relation-ship.json
@@ -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
index 0000000..f78ddfa
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/business-project.json
@@ -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
index 0000000..f6bf992
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/cloud-region-related-link.json
@@ -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
index 0000000..fa32840
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/cloud-region.json
@@ -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
index 0000000..65d6095
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/esr-system-info.json
@@ -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
index 0000000..5239527
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/esr-vnfm.json
@@ -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
index 0000000..2c00ea3
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-orch-status-update.json
@@ -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
index 0000000..388773b
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-related-link.json
@@ -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
index 0000000..25f317a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf-relationship.json
@@ -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
index 0000000..3740ce1
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/generic-vnf.json
@@ -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
index 0000000..5ec5e9f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/line-of-business-related-link.json
@@ -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
index 0000000..61746a2
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/line-of-business.json
@@ -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
index 0000000..c266226
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/owning-entity-relation-ship.json
@@ -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
index 0000000..7248d41
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/owning-entity.json
@@ -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
index 0000000..6e0de8e
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/platform-related-link.json
@@ -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
index 0000000..d94f2f0
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/platform.json
@@ -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
index 0000000..fdd865d
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/pnf.json
@@ -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
index 0000000..c266226
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/relation-ship.json
@@ -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
index 0000000..ab643d3
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-Instance-relationShip.json
@@ -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
index 0000000..5cd566a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-instance-orch-status-update.json
@@ -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
index 0000000..18ae8cb
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-instance.json
@@ -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
index 0000000..e1b4f4f
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/service-subscription.json
@@ -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
index 0000000..eb96c8c
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/tenant-relationship.json
@@ -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
index 0000000..746131a
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/tenant.json
@@ -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
index 0000000..5fa1843
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/aai-simulator/src/test/resources/test-data/vServer.json
@@ -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
index 0000000..340894e
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/common/pom.xml
@@ -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
index 0000000..6a10197
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/cache/provider/AbstractCacheServiceProvider.java
@@ -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
index 0000000..5d59cbb
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/configuration/SimulatorSecurityConfigurer.java
@@ -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
index 0000000..48d5622
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/model/User.java
@@ -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
index 0000000..f12c247
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/main/java/org/onap/so/simulator/model/UserCredentials.java
@@ -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
index 0000000..8ae9b8b
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/common/src/test/java/org/onap/so/simulator/model/PojoClassesTest.java
@@ -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
index 0000000..b3d617d
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/pom.xml
@@ -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
index 0000000..efd7833
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/Dockerfile.so-simulator-base-image
@@ -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
index 0000000..faf8492
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/Dockerfile.workaround-job-container
@@ -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
index 0000000..13c9187
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/configs/logging/logback-spring.xml
@@ -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
index 0000000..eb8ee2e
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/package/docker/src/main/docker/docker-files/scripts/start-app.sh
@@ -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
index 0000000..05c9741
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/package/pom.xml
@@ -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
index 0000000..0cd467b
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/simulator/pom.xml
@@ -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
index 0000000..8c94452
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/so_setup.sh
@@ -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
index 0000000..e2fbdb7
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/so/so_teardown.sh
@@ -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
index 0000000..a9d9bdd
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/teardown.sh
@@ -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
index 0000000..23b45d3
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/test.properties
@@ -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
index 0000000..61a3139
--- /dev/null
+++ b/plans/usecases/pnf-sw-upgrade/testplan.txt
@@ -0,0 +1,4 @@
+# Test suites are relative paths under [integration/csit.git]/tests/.
+# Place the suites in run order.
+usecases/pnf-sw-upgrade
+