Merge "Add Pnf BBs to Service-Macro-Create flow"
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-adapter-ext-clients/src/main/resources/ETSI-Catalog-API.json b/adapters/mso-vnfm-adapter/mso-vnfm-adapter-ext-clients/src/main/resources/ETSI-Catalog-API.json
index 9827310..3c5ec49 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-adapter-ext-clients/src/main/resources/ETSI-Catalog-API.json
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-adapter-ext-clients/src/main/resources/ETSI-Catalog-API.json
@@ -2350,7 +2350,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "nsdId": {
@@ -2358,7 +2358,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "nsdName": {
@@ -2384,7 +2384,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "vnfPkgIds": {
@@ -2392,7 +2392,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "nestedNsdInfoIds": {
@@ -2400,7 +2400,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "nsdOnboardingState": {
@@ -2432,7 +2432,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "pnfdId": {
@@ -2440,7 +2440,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "pnfdName": {
@@ -2475,7 +2475,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "pnfdOnboardingState": {
@@ -2767,7 +2767,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "vnfPkgId": {
@@ -2775,7 +2775,7 @@
           "type": "array",
           "items": {
             "type": "string",
-            "format": "uuid"
+            "minLength": 1
           }
         },
         "operationalState": {
@@ -2804,7 +2804,7 @@
           "title": "Id",
           "description": "Identifier of this subscription resource.",
           "type": "string",
-          "format": "uuid"
+          "minLength": 1
         },
         "callbackUri": {
           "title": "Callbackuri",
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/Constants.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/Constants.java
index 40be441..fb32fb9 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/Constants.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/Constants.java
@@ -21,7 +21,10 @@
 package org.onap.so.adapters.vnfmadapter;
 
 /**
- * Adapter constants
+ * VNFM Adapter constants
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
  */
 public class Constants {
 
@@ -29,8 +32,15 @@
     public static final String SERVICE_VERSION = "v1";
     public static final String BASE_URL = "/so/" + SERVICE_NAME + "/" + SERVICE_VERSION;
     public static final String PACKAGE_MANAGEMENT_BASE_URL = BASE_URL + "/vnfpkgm/v1";
+    public static final String ETSI_SUBSCRIPTION_NOTIFICATION_BASE_URL = BASE_URL + "/etsicatalogmanager/notification";
+    public static final String ETSI_SUBSCRIPTION_NOTIFICATION_CONTROLLER_BASE_URL = BASE_URL + "/etsicatalogmanager";
     public static final String APPLICATION_ZIP = "application/zip";
     public static final String OPERATION_NOTIFICATION_ENDPOINT = "/lcn/VnfLcmOperationOccurrenceNotification";
 
+    /**
+     * Name of the subscription cache
+     */
+    public static final String PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE = "PackageManagementSubscriptionCache";
+
     private Constants() {}
 }
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/MessageConverterConfiguration.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/MessageConverterConfiguration.java
index 84282e0..61d5adf 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/MessageConverterConfiguration.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/MessageConverterConfiguration.java
@@ -23,7 +23,8 @@
 import com.google.gson.GsonBuilder;
 import java.util.ArrayList;
 import java.util.Collection;
-import org.onap.so.adapters.vnfmadapter.converters.Sol003EtsiVnfPkgInfoToPkgmInlineResponse2001Converter;
+import org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003.VnfPkgInfoConverter;
+import org.onap.so.adapters.vnfmadapter.converters.sol003.etsicatalog.PkgmSubscriptionRequestConverter;
 import org.onap.so.adapters.vnfmadapter.oauth.OAuth2AccessTokenAdapter;
 import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
 import org.springframework.context.annotation.Bean;
@@ -43,7 +44,8 @@
     @Bean
     public ConversionService conversionService() {
         final DefaultConversionService service = new DefaultConversionService();
-        service.addConverter(new Sol003EtsiVnfPkgInfoToPkgmInlineResponse2001Converter());
+        service.addConverter(new VnfPkgInfoConverter());
+        service.addConverter(new PkgmSubscriptionRequestConverter());
         return service;
     }
 
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/VnfmAdapterApplication.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/VnfmAdapterApplication.java
index 62d2f7e..405bf89 100755
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/VnfmAdapterApplication.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/VnfmAdapterApplication.java
@@ -27,6 +27,7 @@
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
+import org.springframework.cache.annotation.EnableCaching;
 
 /**
  * The spring boot application for the VNFM (Virtual Network Function Manager) Adapter.
@@ -37,6 +38,7 @@
  * @see <a href= "https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/003/02.05.01_60/gs_nfv-sol003v020501p.pdf">ETSI
  *      SOL003 v2.5.1</a>
  */
+@EnableCaching
 @SpringBootApplication(scanBasePackages = {"org.onap.so"})
 @EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class})
 public class VnfmAdapterApplication {
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/VnfmBasicWebSecurityConfigurerAdapter.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/VnfmBasicWebSecurityConfigurerAdapter.java
index 4f3bbe6..a540460 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/VnfmBasicWebSecurityConfigurerAdapter.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/VnfmBasicWebSecurityConfigurerAdapter.java
@@ -23,14 +23,16 @@
 package org.onap.so.adapters.vnfmadapter;
 
 import org.onap.so.security.SoBasicWebSecurityConfigurerAdapter;
+import org.onap.so.security.SoUserCredentialConfiguration;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 
-
 /**
  * @author Waqas Ikram (waqas.ikram@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
  *
  */
 @EnableWebSecurity
@@ -39,6 +41,7 @@
 
     @Value("${server.ssl.client-auth:none}")
     private String clientAuth;
+    SoUserCredentialConfiguration soUserCredentialConfiguration;
 
     @Override
     protected void configure(final HttpSecurity http) throws Exception {
@@ -46,8 +49,8 @@
             http.csrf().disable().authorizeRequests().anyRequest().permitAll();
         } else {
             super.configure(http);
+            http.authorizeRequests().antMatchers(HttpMethod.GET, "/etsi/subscription/notification").permitAll();
         }
     }
-
 }
 
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/Sol003EtsiVnfPkgInfoToPkgmInlineResponse2001Converter.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/VnfPkgInfoConverter.java
similarity index 85%
rename from adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/Sol003EtsiVnfPkgInfoToPkgmInlineResponse2001Converter.java
rename to adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/VnfPkgInfoConverter.java
index de18ecc..160b875 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/Sol003EtsiVnfPkgInfoToPkgmInlineResponse2001Converter.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/etsicatalog/sol003/VnfPkgInfoConverter.java
@@ -18,28 +18,36 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.so.adapters.vnfmadapter.converters;
+package org.onap.so.adapters.vnfmadapter.converters.etsicatalog.sol003;
 
-import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.*;
-import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.*;
+import java.util.ArrayList;
+import java.util.List;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.core.convert.converter.Converter;
 import org.springframework.stereotype.Service;
-import java.util.ArrayList;
-import java.util.List;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPkgInfo;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.InlineResponse2001;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.VnfPackagesChecksum;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.VnfPackagesSoftwareImages;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPackageSoftwareImageInfo;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.VnfPackagesAdditionalArtifacts;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPackageArtifactInfo;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.VnfPackagesLinks;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.VnfPackagesLinksSelf;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VNFPKGMLinkSerializer;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.Checksum;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.UriLink;
 
 /**
- * Converter to convert from an Etsi Catalog Model {@link VnfPkgInfo} Object to a PackageManagement Model
+ * Converter to convert from an Etsi Catalog Manager {@link VnfPkgInfo} Object to its equivalent SOL003 Object
  * {@link InlineResponse2001} Object
  *
  * @author andrew.a.lamb@est.tech
  */
 @Service
-public class Sol003EtsiVnfPkgInfoToPkgmInlineResponse2001Converter
-        implements Converter<VnfPkgInfo, InlineResponse2001> {
-    private static final Logger logger =
-            LoggerFactory.getLogger(Sol003EtsiVnfPkgInfoToPkgmInlineResponse2001Converter.class);
+public class VnfPkgInfoConverter implements Converter<VnfPkgInfo, InlineResponse2001> {
+    private static final Logger logger = LoggerFactory.getLogger(VnfPkgInfoConverter.class);
 
     /**
      * Convert a {@link VnfPkgInfo} Object to an {@link InlineResponse2001} Object
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/sol003/etsicatalog/PkgmSubscriptionRequestConverter.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/sol003/etsicatalog/PkgmSubscriptionRequestConverter.java
new file mode 100644
index 0000000..c6d51c9
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/converters/sol003/etsicatalog/PkgmSubscriptionRequestConverter.java
@@ -0,0 +1,181 @@
+/*-
+ * ============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.adapters.vnfmadapter.converters.sol003.etsicatalog;
+
+import static org.slf4j.LoggerFactory.getLogger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import javax.swing.text.html.Option;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.Version;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfProducts;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfProductsProviders;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilter;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilter.NotificationTypesEnum;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilter.OperationalStateEnum;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilterVersions;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilterVnfProducts;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilterVnfProductsFromProviders;
+import org.slf4j.Logger;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Service;
+
+/**
+ * Converter to convert from an Etsi Catalog Manager {@link PkgmSubscriptionRequest} Object to its equivalent ETSI
+ * Catalog Manager Object
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ *
+ */
+@Service
+public class PkgmSubscriptionRequestConverter implements
+        Converter<PkgmSubscriptionRequest, org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest> {
+
+    private static final Logger logger = getLogger(PkgmSubscriptionRequestConverter.class);
+
+    @Override
+    public org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest convert(
+            PkgmSubscriptionRequest pkgmSubscriptionRequest) {
+        final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest =
+                new org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest();
+
+        etsiCatalogManagerSubscriptionRequest
+                .setFilters(getPkgmNotificationsFilter(pkgmSubscriptionRequest.getFilter()));
+
+        return etsiCatalogManagerSubscriptionRequest;
+    }
+
+
+    private org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter getPkgmNotificationsFilter(
+            final SubscriptionsFilter sol003SubscriptionsFilter) {
+        final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter etsiCatalogManagerFilters =
+                new org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter();
+
+        if (sol003SubscriptionsFilter.getNotificationTypes() != null) {
+            etsiCatalogManagerFilters.setNotificationTypes(
+                    getPkgmNotificationsFilterNotificationTypes(sol003SubscriptionsFilter.getNotificationTypes()));
+        }
+
+        etsiCatalogManagerFilters.setVnfProductsFromProviders(
+                getVnfProductsProviders(sol003SubscriptionsFilter.getVnfProductsFromProviders()));
+
+        etsiCatalogManagerFilters.setVnfdId(getVnfdIds(sol003SubscriptionsFilter.getVnfdId()));
+
+        etsiCatalogManagerFilters.setVnfPkgId(getVnfPkgIds(sol003SubscriptionsFilter.getVnfPkgId()));
+
+        etsiCatalogManagerFilters
+                .setOperationalState(getOperationalState(sol003SubscriptionsFilter.getOperationalState()));
+
+        etsiCatalogManagerFilters.setUsageState(null);
+
+        return etsiCatalogManagerFilters;
+    }
+
+    // TODO 'operationalState' in the Sol003 Swagger is type 'OperationalStateEnum'. The ETSI Catalog Manager Swagger
+    // 'operationalState' is type 'List<OperationalStateEnum>'. This method needs to be updated once swagger is updated.
+    private List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.OperationalStateEnum> getOperationalState(
+            final OperationalStateEnum operationalState) {
+        if (operationalState != null) {
+            return Arrays.asList(
+                    org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.OperationalStateEnum
+                            .fromValue(operationalState.getValue()));
+        }
+        return Collections.emptyList();
+    }
+
+    private List<String> getVnfPkgIds(final List<String> vnfPkgId) {
+        if (vnfPkgId != null) {
+            final List<String> etsiCatalogManagerVnfPkgId = new ArrayList<>();
+            vnfPkgId.forEach(type -> {
+                etsiCatalogManagerVnfPkgId.add(type);
+            });
+        }
+        return Collections.emptyList();
+    }
+
+    private List<String> getVnfdIds(final List<String> vnfdId) {
+        if (vnfdId != null) {
+            final List<String> etsiCatalogManagerVnfdId = new ArrayList<>();
+            vnfdId.forEach(type -> {
+                etsiCatalogManagerVnfdId.add(type);
+            });
+        }
+        return Collections.emptyList();
+    }
+
+    private List<VnfProductsProviders> getVnfProductsProviders(
+            final List<SubscriptionsFilterVnfProductsFromProviders> filterProductsFromProvider) {
+
+        if (filterProductsFromProvider != null && !filterProductsFromProvider.isEmpty()) {
+            final List<VnfProductsProviders> etsiCatalogManagerVnfProductsProviders = new ArrayList<>();
+            filterProductsFromProvider.forEach(vnfProduct -> {
+                etsiCatalogManagerVnfProductsProviders
+                        .add(new VnfProductsProviders().vnfProducts(getVnfProducts(vnfProduct.getVnfProducts())));
+            });
+            return etsiCatalogManagerVnfProductsProviders;
+        }
+        return Collections.emptyList();
+    }
+
+    private List<VnfProducts> getVnfProducts(final List<SubscriptionsFilterVnfProducts> sol003VnfProducts) {
+        if (sol003VnfProducts != null) {
+            final List<VnfProducts> etsiCatalogManagerVnfProductsList = new ArrayList<>();
+            sol003VnfProducts.forEach(vnfProduct -> {
+                etsiCatalogManagerVnfProductsList.add(new VnfProducts().vnfProductName(vnfProduct.getVnfProductName())
+                        .versions(getVersion(vnfProduct.getVersions())));
+            });
+            return etsiCatalogManagerVnfProductsList;
+        }
+        return Collections.emptyList();
+    }
+
+    private List<Version> getVersion(final List<SubscriptionsFilterVersions> sol003FilterVersions) {
+        if (sol003FilterVersions != null && !sol003FilterVersions.isEmpty()) {
+            List<Version> etsiCatalogVersionList = new ArrayList<>();
+            sol003FilterVersions.forEach(vnfFilterVersion -> {
+                etsiCatalogVersionList.add(new Version().vnfSoftwareVersion(vnfFilterVersion.getVnfSoftwareVersion())
+                        .vnfdVersions(vnfFilterVersion.getVnfdVersions()));
+            });
+            return etsiCatalogVersionList;
+        }
+        return Collections.emptyList();
+    }
+
+    private List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.NotificationTypesEnum> getPkgmNotificationsFilterNotificationTypes(
+            final List<NotificationTypesEnum> notificationTypes) {
+
+        if (notificationTypes != null && !notificationTypes.isEmpty()) {
+            final List<org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.NotificationTypesEnum> etsiCatalogManagerNotificationTypes =
+                    new ArrayList<>();
+            notificationTypes.forEach(type -> etsiCatalogManagerNotificationTypes.add(
+                    org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter.NotificationTypesEnum
+                            .fromValue(type.getValue())));
+        }
+        return Collections.emptyList();
+    }
+
+
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProvider.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProvider.java
index 34fc264..62b3657 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProvider.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProvider.java
@@ -21,7 +21,9 @@
 package org.onap.so.adapters.vnfmadapter.extclients.etsicatalog;
 
 import java.util.Optional;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscription;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.InlineResponse2001;
+import org.springframework.http.ResponseEntity;
 
 /**
  * Provides methods for invoking REST calls to the ETSI Catalog Manager.
@@ -71,4 +73,12 @@
      */
     Optional<byte[]> getVnfPackageArtifact(final String vnfPkgId, final String artifactPath);
 
+    /**
+     * Post the SubscriptionRequest Object.
+     *
+     * @return The ResponseEntity containing the ETSI Catalog Manager's PkgmSubscription object.
+     */
+    Optional<PkgmSubscription> postSubscription(
+            final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest);
+
 }
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderImpl.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderImpl.java
index 779cb2a..1a48494 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderImpl.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogServiceProviderImpl.java
@@ -21,6 +21,8 @@
 package org.onap.so.adapters.vnfmadapter.extclients.etsicatalog;
 
 import java.util.Optional;
+import javax.swing.text.html.Option;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscription;
 import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.VnfPkgInfo;
 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.InlineResponse2001;
 import org.onap.so.adapters.vnfmadapter.rest.exceptions.*;
@@ -102,6 +104,7 @@
             if (response.getStatusCode() == HttpStatus.OK) {
                 if (response.hasBody()) {
                     final VnfPkgInfo[] vnfPackages = response.getBody();
+                    assert (vnfPackages != null);
                     final InlineResponse2001[] responses = new InlineResponse2001[vnfPackages.length];
                     for (int index = 0; index < vnfPackages.length; index++) {
                         if (conversionService.canConvert(vnfPackages[index].getClass(), InlineResponse2001.class)) {
@@ -113,7 +116,7 @@
                         }
                         logger.error("Unable to find Converter for response class: {}", vnfPackages[index].getClass());
                     }
-                    return Optional.ofNullable(responses);
+                    return Optional.of(responses);
                 }
                 logger.error("Received response without body ...");
             }
@@ -170,6 +173,33 @@
         return requestVnfElement(vnfPkgId, vnfRequestUrl, vnfRequestName);
     }
 
+    @Override
+    public Optional<PkgmSubscription> postSubscription(
+            final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest) {
+        try {
+            final ResponseEntity<PkgmSubscription> responseEntity =
+                    httpServiceProvider.postHttpRequest(etsiCatalogManagerSubscriptionRequest,
+                            etsiCatalogUrlProvider.getSubscriptionUrl(), PkgmSubscription.class);
+            if (responseEntity.getStatusCode() == HttpStatus.OK) {
+                if (responseEntity.hasBody()) {
+                    return Optional.of(responseEntity.getBody());
+                }
+                logger.error("Received response without body on postSubscription");
+            }
+            logger.error("Unexpected Status Code Received on postSubscription: {}", responseEntity.getStatusCode());
+            return Optional.empty();
+        } catch (final InvalidRestRequestException invalidRestRequestException) {
+            logger.error("Caught InvalidRestRequestException", invalidRestRequestException);
+            throw new EtsiCatalogManagerBadRequestException("Bad Request Received on postSubscription call.");
+        } catch (final RestProcessingException restProcessingException) {
+            logger.error("Caught RestProcessingException with Status Code: {}", restProcessingException.getStatusCode(),
+                    restProcessingException);
+            throw new EtsiCatalogManagerRequestFailureException(
+                    "Internal Server Error Occurred. On postSubscription with StatusCode: "
+                            + restProcessingException.getStatusCode());
+        }
+    }
+
     private Optional<byte[]> requestVnfElement(final String vnfPkgId, final String vnfRequestUrl,
             final String vnfRequestName) {
         try {
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogUrlProvider.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogUrlProvider.java
index 8382212..3b4c4c3 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogUrlProvider.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/extclients/etsicatalog/EtsiCatalogUrlProvider.java
@@ -99,4 +99,15 @@
         logger.info("getEtsiCatalogVnfPackageVnfd: {}", url);
         return url;
     }
+
+    /**
+     * Get the URL for posting/retrieving a Subscription
+     *
+     * @return the URL for the operation
+     */
+    public String getSubscriptionUrl() {
+        final String url = etsiCatalogManagerEndpoint + "/subscriptions";
+        logger.info("getSubscriptionNotificationUrl: {}", url);
+        return url;
+    }
 }
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/SubscriptionManager.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/SubscriptionManager.java
new file mode 100644
index 0000000..30a16f7
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/SubscriptionManager.java
@@ -0,0 +1,196 @@
+/*-
+ * ============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.adapters.vnfmadapter.packagemanagement.subscriptionmanagement;
+
+import static org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.SubscriptionAuthentication.AuthTypeEnum.BASIC;
+import static org.slf4j.LoggerFactory.getLogger;
+import java.net.URI;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import org.onap.so.adapters.vnfmadapter.Constants;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.EtsiCatalogServiceProvider;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.EtsiCatalogUrlProvider;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.BasicAuth;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscription;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.InlineResponse2002;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsLinks;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.VnfPackagesLinksSelf;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache.PackageManagementCacheServiceProvider;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.InternalServerErrorException;
+import org.onap.so.adapters.vnfmadapter.rest.exceptions.SubscriptionRequestConversionException;
+import org.onap.so.rest.service.HttpRestServiceProvider;
+import org.onap.so.utils.CryptoUtils;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.convert.ConversionException;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.stereotype.Service;
+
+/**
+ * Manages package management subscriptions from the VNFMs
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ *
+ */
+@Service
+public class SubscriptionManager {
+
+    private static final Logger logger = getLogger(SubscriptionManager.class);
+    private final PackageManagementCacheServiceProvider packageManagementCacheServiceProvider;
+    private final EtsiCatalogUrlProvider etsiCatalogUrlProvider;
+    private final HttpRestServiceProvider httpServiceProvider;
+    private final ConversionService conversionService;
+    private final EtsiCatalogServiceProvider etsiCatalogServiceProvider;
+    private final String vnfmAdapterEndpoint;
+    private final String msoKeyString;
+    private final String vnfmAdapterAuth;
+
+
+    @Autowired
+    public SubscriptionManager(final PackageManagementCacheServiceProvider packageManagementCacheServiceProvider,
+            final ConversionService conversionService, final HttpRestServiceProvider httpServiceProvider,
+            final EtsiCatalogUrlProvider etsiCatalogUrlProvider,
+            final EtsiCatalogServiceProvider etsiCatalogServiceProvider,
+            @Value("${vnfmadapter.endpoint}") final String vnfmAdapterEndpoint,
+            @Value("${mso.key}") final String msoKeyString,
+            @Value("${vnfmadapter.auth:D6CFE56451508B75536C5E8A1E7AE06D0346006A693BF29293A6E1C762EFD59C671911DB6E9294E4FE15E4C1C5524B}") final String vnfmAdapterAuth) {
+        this.packageManagementCacheServiceProvider = packageManagementCacheServiceProvider;
+        this.etsiCatalogUrlProvider = etsiCatalogUrlProvider;
+        this.conversionService = conversionService;
+        this.httpServiceProvider = httpServiceProvider;
+        this.etsiCatalogServiceProvider = etsiCatalogServiceProvider;
+        this.vnfmAdapterEndpoint = vnfmAdapterEndpoint;
+        this.vnfmAdapterAuth = vnfmAdapterAuth;
+        this.msoKeyString = msoKeyString;
+    }
+
+    public Optional<InlineResponse2002> createSubscription(final PkgmSubscriptionRequest pkgmSubscriptionRequest)
+            throws GeneralSecurityException {
+
+        final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest =
+                buildEtsiCatalogManagerPkgmSubscriptionRequest(pkgmSubscriptionRequest);
+
+        final Optional<PkgmSubscription> optionalEtsiCatalogManagerSubscription =
+                etsiCatalogServiceProvider.postSubscription(etsiCatalogManagerSubscriptionRequest);
+
+        if (optionalEtsiCatalogManagerSubscription.isPresent()) {
+            PkgmSubscription etsiCatalogManagerSubscription = optionalEtsiCatalogManagerSubscription.get();
+            logger.debug("postPkgmSubscriptionRequest Response SubscriptionId: {}",
+                    Objects.requireNonNull(etsiCatalogManagerSubscription.getId().toString()));
+            final String subscriptionId = etsiCatalogManagerSubscription.getId().toString();
+
+            packageManagementCacheServiceProvider.addSubscription(subscriptionId, pkgmSubscriptionRequest);
+
+            final InlineResponse2002 response2002 = new InlineResponse2002();
+            response2002.setId(subscriptionId);
+            response2002.setFilter(pkgmSubscriptionRequest.getFilter());
+            response2002.setCallbackUri(getSubscriptionUri(subscriptionId).toString());
+            response2002.setLinks(new SubscriptionsLinks()
+                    .self(new VnfPackagesLinksSelf().href(getSubscriptionUri(subscriptionId).toString())));
+
+            return Optional.of(response2002);
+        }
+        throw new InternalServerErrorException(
+                "Received empty response from POST to ETSI Catalog Manager Subscription Endpoint.");
+    }
+
+
+
+    public Optional<String> getSubscriptionId(final PkgmSubscriptionRequest pkgmSubscriptionRequest) {
+        return packageManagementCacheServiceProvider.getSubscriptionId(pkgmSubscriptionRequest);
+    }
+
+    public Optional<InlineResponse2002> getSubscription(final String subscriptionId) {
+        final Optional<PkgmSubscriptionRequest> optional =
+                packageManagementCacheServiceProvider.getSubscription(subscriptionId);
+        if (optional.isPresent()) {
+            final PkgmSubscriptionRequest subscription = optional.get();
+            return Optional.of(getInlineResponse2002(subscriptionId, subscription));
+        }
+        return Optional.empty();
+    }
+
+    public List<InlineResponse2002> getSubscriptions() {
+        final Map<String, PkgmSubscriptionRequest> subscriptions =
+                packageManagementCacheServiceProvider.getSubscriptions();
+        final List<InlineResponse2002> response = new ArrayList<>();
+        subscriptions.forEach((key, value) -> response.add(getInlineResponse2002(key, value)));
+        return response;
+    }
+
+    public URI getSubscriptionUri(final String subscriptionId) {
+        return URI.create(
+                vnfmAdapterEndpoint + Constants.PACKAGE_MANAGEMENT_BASE_URL + "/subscriptions/" + subscriptionId);
+    }
+
+    private InlineResponse2002 getInlineResponse2002(final String id, final PkgmSubscriptionRequest subscription) {
+        return new InlineResponse2002().id(id).filter(subscription.getFilter())
+                .callbackUri(subscription.getCallbackUri());
+    }
+
+    private org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest buildEtsiCatalogManagerPkgmSubscriptionRequest(
+            PkgmSubscriptionRequest pkgmSubscriptionRequest) throws GeneralSecurityException {
+
+        final org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest etsiCatalogManagerSubscriptionRequest;
+        try {
+            etsiCatalogManagerSubscriptionRequest = conversionService.convert(pkgmSubscriptionRequest,
+                    org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscriptionRequest.class);
+        } catch (ConversionException conversionException) {
+            logger.error(conversionException.getMessage());
+            throw new SubscriptionRequestConversionException(
+                    "Could not convert Sol003 PkgmSubscriptionRequest to ETSI-Catalog Manager PkgmSubscriptionRequest");
+        } catch (Exception exception) {
+            logger.error(exception.getMessage());
+            throw new InternalServerErrorException(
+                    "Could not convert Sol003 PkgmSubscriptionRequest to ETSI-Catalog Manager PkgmSubscriptionRequest");
+        }
+
+        if (etsiCatalogManagerSubscriptionRequest != null) {
+            etsiCatalogManagerSubscriptionRequest
+                    .setCallbackUri(vnfmAdapterEndpoint + Constants.ETSI_SUBSCRIPTION_NOTIFICATION_BASE_URL);
+
+            final String[] auth = decryptAuth();
+            final String username = auth[0];
+            final String password = auth[1];
+
+            etsiCatalogManagerSubscriptionRequest.setAuthentication(
+                    new org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.SubscriptionAuthentication()
+                            .addAuthTypeItem(BASIC).paramsBasic(new BasicAuth().userName(username).password(password)));
+            return etsiCatalogManagerSubscriptionRequest;
+        }
+        throw new SubscriptionRequestConversionException(
+                "Failed to convert Sol003 PkgmSubscriptionRequest to ETSI-Catalog Manager PkgmSubscriptionRequest");
+    }
+
+    private String[] decryptAuth() throws GeneralSecurityException {
+        final String decryptedAuth = CryptoUtils.decrypt(vnfmAdapterAuth, msoKeyString);
+        final String[] auth = decryptedAuth.split(":");
+        return auth;
+    }
+
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/AbstractCacheServiceProvider.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/AbstractCacheServiceProvider.java
new file mode 100644
index 0000000..e1e9b23
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/AbstractCacheServiceProvider.java
@@ -0,0 +1,47 @@
+/*-
+ * ============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.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+
+/**
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+public abstract class AbstractCacheServiceProvider {
+
+    private final CacheManager cacheManager;
+    private final String cacheName;
+
+    public AbstractCacheServiceProvider(final String cacheName, final CacheManager cacheManager) {
+        this.cacheName = cacheName;
+        this.cacheManager = cacheManager;
+    }
+
+    public Cache getCache() {
+        final Cache cache = cacheManager.getCache(cacheName);
+        if (cache == null) {
+            throw new CacheNotFoundException("Unable to find " + cacheName + " cache");
+        }
+        return cache;
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheManagerConfiguration.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheManagerConfiguration.java
new file mode 100644
index 0000000..830db39
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheManagerConfiguration.java
@@ -0,0 +1,50 @@
+/*-
+ * ============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.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+import java.util.Arrays;
+import org.onap.so.adapters.vnfmadapter.Constants;
+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;
+
+/**
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Configuration
+public class CacheManagerConfiguration {
+
+    @Bean
+    public CacheManager cacheManager() {
+        final SimpleCacheManager manager = new SimpleCacheManager();
+        manager.setCaches(Arrays.asList(getCache(Constants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE)));
+
+        return manager;
+    }
+
+    private Cache getCache(final String name) {
+        return new ConcurrentMapCache(name);
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheNotFoundException.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheNotFoundException.java
new file mode 100644
index 0000000..edd5982
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/CacheNotFoundException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============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.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+/**
+ * Exception for failure to find the cache.
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ *
+ */
+public class CacheNotFoundException extends RuntimeException {
+
+    private static final long serialVersionUID = -372361485260755367L;
+
+    public CacheNotFoundException(final String message) {
+        super(message);
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProvider.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProvider.java
new file mode 100644
index 0000000..6042513
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProvider.java
@@ -0,0 +1,74 @@
+/*-
+ * ============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.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+import java.util.Map;
+import java.util.Optional;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.PkgmSubscriptionRequest;
+
+/**
+ * Interface which provides methods for communicating with the cache
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ *
+ */
+public interface PackageManagementCacheServiceProvider {
+
+    /**
+     * Checks cache if subscription request Id is already present. If not, it adds the subscription to the cache.
+     * 
+     * @param subscriptionId
+     * @param pkgmSubscriptionRequest
+     */
+    void addSubscription(final String subscriptionId, final PkgmSubscriptionRequest pkgmSubscriptionRequest);
+
+    /**
+     * Gets individual subscription from cache
+     * 
+     * @param subscriptionId
+     * @return <AbstractMap.SimpleImmutableEntry<String, PkgmSubscriptionRequest>>
+     */
+    Optional<PkgmSubscriptionRequest> getSubscription(final String subscriptionId);
+
+    /**
+     * Gets Map of subscriptions from cache
+     * 
+     * @return Map<String, PkgmSubscriptionRequest>>
+     */
+    Map<String, PkgmSubscriptionRequest> getSubscriptions();
+
+    /**
+     * Delete subscription from cache
+     * 
+     * @param subscriptionId
+     * @return true if subscription exists and able to be removed, otherwise returns false
+     */
+    boolean deleteSubscription(final String subscriptionId);
+
+    /**
+     * Checks if subscription exists in cache and return its subscriptionId
+     * 
+     * @param pkgmSubscriptionRequest
+     * @return Subscription Id
+     */
+    Optional<String> getSubscriptionId(final PkgmSubscriptionRequest pkgmSubscriptionRequest);
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProviderImpl.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProviderImpl.java
new file mode 100644
index 0000000..ba57eb5
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/packagemanagement/subscriptionmanagement/cache/PackageManagementCacheServiceProviderImpl.java
@@ -0,0 +1,119 @@
+/*-
+ * ============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.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.cache;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import org.onap.so.adapters.vnfmadapter.Constants;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.PkgmSubscriptionRequest;
+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;
+
+/**
+ * Implementation which provides methods for communicating with the cache
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Service
+public class PackageManagementCacheServiceProviderImpl extends AbstractCacheServiceProvider
+        implements PackageManagementCacheServiceProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PackageManagementCacheServiceProviderImpl.class);
+
+    @Autowired
+    public PackageManagementCacheServiceProviderImpl(final CacheManager cacheManager) {
+        super(Constants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE, cacheManager);
+    }
+
+    @Override
+    public void addSubscription(final String subscriptionId, final PkgmSubscriptionRequest pkgmSubscriptionRequest) {
+        LOGGER.debug("Adding {} to cache with subscription id: {}", pkgmSubscriptionRequest, subscriptionId);
+        getCache().put(subscriptionId, pkgmSubscriptionRequest);
+    }
+
+    @Override
+    public Optional<PkgmSubscriptionRequest> getSubscription(final String subscriptionId) {
+        LOGGER.debug("Getting subscription from cache using Id: {}", subscriptionId);
+        final Cache cache = getCache();
+        final PkgmSubscriptionRequest cacheValue = cache.get(subscriptionId, PkgmSubscriptionRequest.class);
+        if (cacheValue != null) {
+            return Optional.of(cacheValue);
+        }
+        LOGGER.error("Unable to find Subscription in cache using Id: {}", subscriptionId);
+        return Optional.empty();
+    }
+
+    @Override
+    public Map<String, PkgmSubscriptionRequest> getSubscriptions() {
+        LOGGER.info("Getting all subscriptions from cache");
+        final Cache cache = getCache();
+
+        final Object nativeCache = cache.getNativeCache();
+        if (nativeCache instanceof ConcurrentHashMap) {
+            @SuppressWarnings("unchecked")
+            final ConcurrentHashMap<Object, Object> concurrentHashMap = (ConcurrentHashMap<Object, Object>) nativeCache;
+            final Map<String, PkgmSubscriptionRequest> result = new HashMap<>();
+            concurrentHashMap.keySet().forEach(key -> {
+                final Optional<PkgmSubscriptionRequest> optional = getSubscription(key.toString());
+                optional.ifPresent(pkgmSubscriptionRequest -> result.put(key.toString(), pkgmSubscriptionRequest));
+            });
+            return result;
+        }
+        LOGGER.error("Unable to find Subscriptions in cache");
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public boolean deleteSubscription(final String subscriptionId) {
+        final Cache cache = getCache();
+        final Optional<PkgmSubscriptionRequest> optional = getSubscription(subscriptionId);
+        if (optional.isPresent()) {
+            cache.evict(subscriptionId);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Optional<String> getSubscriptionId(final PkgmSubscriptionRequest pkgmSubscriptionRequest) {
+        final Cache cache = getCache();
+        final Object nativeCache = cache.getNativeCache();
+        if (nativeCache instanceof ConcurrentHashMap) {
+            @SuppressWarnings("unchecked")
+            final ConcurrentHashMap<Object, Object> concurrentHashMap = (ConcurrentHashMap<Object, Object>) nativeCache;
+            final Optional<Entry<Object, Object>> optional = concurrentHashMap.entrySet().stream()
+                    .filter(entry -> entry.getValue().equals(pkgmSubscriptionRequest)).findAny();
+            if (optional.isPresent()) {
+                return Optional.of(optional.get().getKey().toString());
+            }
+        }
+        return Optional.empty();
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationController.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationController.java
new file mode 100644
index 0000000..c5bd5bc
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/EtsiSubscriptionNotificationController.java
@@ -0,0 +1,51 @@
+/*-
+ * ============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.adapters.vnfmadapter.rest;
+
+import static org.onap.so.adapters.vnfmadapter.Constants.ETSI_SUBSCRIPTION_NOTIFICATION_CONTROLLER_BASE_URL;
+import static org.slf4j.LoggerFactory.getLogger;
+import javax.ws.rs.core.MediaType;
+import org.slf4j.Logger;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * This controller handles the ETSI Subscription Notification Endpoints.
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Controller
+@RequestMapping(value = ETSI_SUBSCRIPTION_NOTIFICATION_CONTROLLER_BASE_URL,
+        produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+        consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+public class EtsiSubscriptionNotificationController {
+
+    private static final Logger logger = getLogger(EtsiSubscriptionNotificationController.class);
+
+    @GetMapping(value = "/notification")
+    public ResponseEntity<Void> testSubscriptionNotificationEndPoint() {
+        logger.debug("Testing Notification Endpoint");
+        return ResponseEntity.noContent().build();
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementController.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementController.java
index 9d8e29b..cce7241 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementController.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementController.java
@@ -75,7 +75,7 @@
                 + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"vnf_packages\" \n"
                 + "endpoint.";
         logger.error(errorMessage);
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(buildProblemDetails(errorMessage));
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
     }
 
     /**
@@ -97,7 +97,7 @@
                 + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"vnf_packages\" by vnfPkgId: \""
                 + vnfPkgId + "\" \n" + "endpoint.";
         logger.error(errorMessage);
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(buildProblemDetails(errorMessage));
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
     }
 
     /**
@@ -121,7 +121,7 @@
                 + "endpoint.";
 
         logger.error(errorMessage);
-        return new ResponseEntity(buildProblemDetails(errorMessage), HttpStatus.INTERNAL_SERVER_ERROR);
+        return new ResponseEntity(new ProblemDetails().detail(errorMessage), HttpStatus.INTERNAL_SERVER_ERROR);
     }
 
     /**
@@ -144,7 +144,7 @@
                 + " Sol003PackageManagementController from the EtsiCatalogManager using the GET \"package_content\" \n"
                 + "endpoint.";
         logger.error(errorMessage);
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(buildProblemDetails(errorMessage));
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
     }
 
     /**
@@ -170,19 +170,9 @@
                 + " Sol003PackageManagementController from the EtsiCatalogManager using the\n GET \"vnf_packages\" by vnfPkgId: \""
                 + vnfPkgId + "\" for artifactPath: \"" + artifactPath + "\"\n" + "endpoint.";
         logger.error(errorMessage);
-        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(buildProblemDetails(errorMessage));
-    }
-
-    /**
-     * Builds the ProblemDetails Object, using the provided error message.
-     * 
-     * @param detail The error message retrieved from the exception thrown.
-     * @return ProblemDetails Object, containing error information.
-     */
-    private ProblemDetails buildProblemDetails(final String detail) {
-        final ProblemDetails problemDetails = new ProblemDetails();
-        problemDetails.setDetail(detail);
-        return problemDetails;
+        // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new
+        // ProblemDetails().detail(errorMessage));
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
     }
 
 }
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionController.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionController.java
new file mode 100644
index 0000000..cbad564
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionController.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.adapters.vnfmadapter.rest;
+
+import static org.onap.so.adapters.vnfmadapter.Constants.PACKAGE_MANAGEMENT_BASE_URL;
+import static org.slf4j.LoggerFactory.getLogger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.GeneralSecurityException;
+import java.util.List;
+import java.util.Optional;
+import javax.ws.rs.core.MediaType;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.InlineResponse2002;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.ProblemDetails;
+import org.onap.so.adapters.vnfmadapter.packagemanagement.subscriptionmanagement.SubscriptionManager;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+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.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Controller for handling the Subscription Management. The client can use this resource to subscribe to notifications
+ * related to the VNF package management, and to query its subscriptions. For further information please read:
+ * https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/003/02.05.01_60/gs_nfv-sol003v020501p.pdf Use the section number
+ * above each endpoint to find the corresponding section in the above document.
+ *
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ */
+@Controller
+@RequestMapping(value = PACKAGE_MANAGEMENT_BASE_URL, produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
+        consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+public class Sol003PackageManagementSubscriptionController {
+
+    private static final String LOG_REQUEST_RECEIVED = "Subscription Management Controller: {} {}";
+    private static final Logger logger = getLogger(Sol003PackageManagementSubscriptionController.class);
+    private final SubscriptionManager subscriptionManager;
+
+    @Autowired
+    public Sol003PackageManagementSubscriptionController(final SubscriptionManager subscriptionManager) {
+        this.subscriptionManager = subscriptionManager;
+    }
+
+    /**
+     * POST Subscribe request. Will send request and respond with the subscription that you subscribed to, if
+     * successful. Section Number: 10.4.7
+     * 
+     * @param pkgmSubscriptionRequest This includes the details of the subscription to be created.
+     * @return The subscription requested, if successful. Object: InlineRespone2002 Response Code: 201 Created Response
+     *         Code: 303 Duplicate Subscription
+     * @throws GeneralSecurityException
+     */
+    @PostMapping(value = "/subscriptions")
+    public ResponseEntity<?> postSubscriptionRequest(@RequestBody final PkgmSubscriptionRequest pkgmSubscriptionRequest)
+            throws GeneralSecurityException {
+        logger.info(LOG_REQUEST_RECEIVED, " postSubscriptionRequest Endpoint Called");
+
+        // Check if subscription exists already.
+        final Optional<String> exists = subscriptionManager.getSubscriptionId(pkgmSubscriptionRequest);
+
+        if (exists.isPresent()) {
+            final URI subscriptionUri = subscriptionManager.getSubscriptionUri(exists.get());
+            final HttpHeaders headers = createLocationHeader(subscriptionUri);
+            logger.info("PkgmSubscriptionRequest already exists with uri {} ", subscriptionUri);
+            return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER);
+        }
+
+        logger.debug("No duplicate Subscription exists, continuing with POST.");
+        final Optional<InlineResponse2002> optionalInlineResponse2002 =
+                subscriptionManager.createSubscription(pkgmSubscriptionRequest);
+
+        if (optionalInlineResponse2002.isPresent()) {
+            InlineResponse2002 inlineResponse2002 = optionalInlineResponse2002.get();
+            final URI subscriptionUri = subscriptionManager.getSubscriptionUri(inlineResponse2002.getId());
+            final HttpHeaders headers = createLocationHeader(subscriptionUri);
+            logger.debug("Sending response with uri {} ", subscriptionUri);
+            return new ResponseEntity<>(inlineResponse2002, headers, HttpStatus.CREATED);
+        }
+        final String errorMessage = "A null response was received during the postSubscriptionRequest call.";
+        logger.error(errorMessage);
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ProblemDetails().detail(errorMessage));
+    }
+
+    /**
+     * GET all subscriptions. Will return a list of all subscriptions currently active. Section Number: 10.4.7
+     * 
+     * @return All of the current active subscriptions. Object: List<InlineResponse2002> Response Code: 200 OK
+     */
+    @GetMapping(value = "/subscriptions")
+    public ResponseEntity<List<InlineResponse2002>> getSubscriptions() {
+        logger.info(LOG_REQUEST_RECEIVED, " getSubscriptions.");
+        List<InlineResponse2002> subscriptionsList = subscriptionManager.getSubscriptions();
+        return new ResponseEntity<>(subscriptionsList, HttpStatus.OK);
+    }
+
+    /**
+     * GET a specific subscription, by subscriptionId. Section Number: 10.4.8
+     * 
+     * @param subscriptionId The ID of the subscription that you wish to retrieve.
+     * @return A subscription based on subscriptionId. Object: InlineResponse2002 Response Code: 200 OK
+     */
+    @GetMapping(value = "/subscriptions/{subscriptionId}")
+    public ResponseEntity<?> getSubscription(@PathVariable("subscriptionId") final String subscriptionId) {
+        logger.info(LOG_REQUEST_RECEIVED, " Getting Subscription: ", subscriptionId);
+        final Optional<InlineResponse2002> optional = subscriptionManager.getSubscription(subscriptionId);
+        if (optional.isPresent()) {
+            logger.debug("Return subscription with id {} and body {}", subscriptionId, optional);
+            return new ResponseEntity<>(optional.get(), HttpStatus.OK);
+        }
+        final String errorMessage =
+                "The requested subscription: " + subscriptionId + " was not found on call getSubscription";
+        logger.error(errorMessage);
+        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ProblemDetails().detail(errorMessage));
+    }
+
+    /**
+     * Method to set the Location in the header with the URI parameter
+     * 
+     * @param subscriptionUri
+     * @return header with callbackUri in Location
+     */
+    private HttpHeaders createLocationHeader(final URI subscriptionUri) {
+        final HttpHeaders headers = new HttpHeaders();
+        headers.setLocation(subscriptionUri);
+        return headers;
+    }
+
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003SubscriptionManagementController.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003SubscriptionManagementController.java
deleted file mode 100644
index 16650d4..0000000
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/Sol003SubscriptionManagementController.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- * ============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.adapters.vnfmadapter.rest;
-
-import static org.onap.so.adapters.vnfmadapter.Constants.PACKAGE_MANAGEMENT_BASE_URL;
-import static org.slf4j.LoggerFactory.getLogger;
-import java.util.List;
-import javax.ws.rs.core.MediaType;
-import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.InlineResponse2002;
-import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.PkgmSubscriptionRequest;
-import org.slf4j.Logger;
-import org.springframework.http.HttpStatus;
-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.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-/**
- * Controller for handling the Subscription Management. For further information please read:
- * https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/003/02.05.01_60/gs_nfv-sol003v020501p.pdf Use the section number
- * above each endpoint to find the corresponding section in the above document.
- *
- * @author gareth.roper@est.tech
- */
-@Controller
-@RequestMapping(value = PACKAGE_MANAGEMENT_BASE_URL, produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML},
-        consumes = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
-public class Sol003SubscriptionManagementController {
-
-    private static final String LOG_REQUEST_RECEIVED = "Subscription Management Controller: {} {}";
-    private static final Logger logger = getLogger(Sol003SubscriptionManagementController.class);
-
-    /**
-     * POST Subscribe request. Will send request and respond with the subscription that you subscribed to, if
-     * successful. Section Number: 10.4.7
-     * 
-     * @param pkgmSubscriptionRequest This includes the details of the subscription to be created.
-     * @return The subscription requested, if successful. Object: InlineRespone2002 Response Code: 201 Created Response
-     *         Code: 303 Duplicate Subscription
-     */
-    @PostMapping(value = "/subscriptions")
-    public ResponseEntity<InlineResponse2002> postSubscriptionRequest(
-            @RequestBody final PkgmSubscriptionRequest pkgmSubscriptionRequest) {
-        logger.info(LOG_REQUEST_RECEIVED, " postSubscriptionRequest: ", pkgmSubscriptionRequest);
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    /**
-     * GET all subscriptions. Will return a list of all subscriptions currently active. Section Number: 10.4.7
-     * 
-     * @return All of the current active subscriptions. Object: List<InlineResponse2002> Response Code: 200 OK
-     */
-    @GetMapping(value = "/subscriptions")
-    public ResponseEntity<List<InlineResponse2002>> getSubscriptions() {
-        logger.info(LOG_REQUEST_RECEIVED, " getSubscriptions.");
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    /**
-     * GET a specific subscription, by subscriptionId. Section Number: 10.4.8
-     * 
-     * @param subscriptionId The ID of the subscription that you wish to retrieve.
-     * @return A subscription based on subscriptionId. Object: InlineResponse2002 Response Code: 200 OK
-     */
-    @GetMapping(value = "/subscriptions/{subscriptionId}")
-    public ResponseEntity<InlineResponse2002> getSubscription(
-            @PathVariable("subscriptionId") final String subscriptionId) {
-        logger.info(LOG_REQUEST_RECEIVED, " Getting Subscription: ", subscriptionId);
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-    /**
-     * DELETE a specific subscription, by subscriptionId. Section Number: 10.4.7
-     * 
-     * @param subscriptionId The ID of the subscription that you wish to delete.
-     * @return Empty response if successful. Object: Void Response Code: 204 No Content
-     */
-    @DeleteMapping(value = "/subscriptions/{subscriptionId}")
-    public ResponseEntity<Void> deleteSubscription(@PathVariable("subscriptionId") final String subscriptionId) {
-        logger.info(LOG_REQUEST_RECEIVED, " Deleting Subscription: ", subscriptionId);
-        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
-    }
-
-
-}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerBadRequestException.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerBadRequestException.java
new file mode 100644
index 0000000..dbd098f
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/EtsiCatalogManagerBadRequestException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============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.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an ETSI Catalog Manager Bad Request Exception.
+ * 
+ * @author Gareth Roper (gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.BAD_REQUEST)
+public class EtsiCatalogManagerBadRequestException extends RuntimeException {
+
+    private static final long serialVersionUID = 6571317418914258768L;
+
+    public EtsiCatalogManagerBadRequestException(final String message) {
+        super(message);
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return this;
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/InternalServerErrorException.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/InternalServerErrorException.java
new file mode 100644
index 0000000..9b547d3
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/InternalServerErrorException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============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.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an ETSI Catalog Manager Request Failure
+ * 
+ * @author gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class InternalServerErrorException extends RuntimeException {
+
+    private static final long serialVersionUID = 66864561537194516L;
+
+    public InternalServerErrorException(final String message) {
+        super(message);
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return this;
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/Sol003PackageManagementControllerExceptionHandler.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/Sol003PackageManagementControllerExceptionHandler.java
index a49063a..da8b0cb 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/Sol003PackageManagementControllerExceptionHandler.java
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/Sol003PackageManagementControllerExceptionHandler.java
@@ -48,6 +48,30 @@
         return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(problemDetails);
     }
 
+    @ExceptionHandler(EtsiCatalogManagerBadRequestException.class)
+    public ResponseEntity<ProblemDetails> handleEtsiCatalogManagerBadRequestFailureException(
+            final EtsiCatalogManagerBadRequestException etsiCatalogManagerBadRequestException) {
+        final ProblemDetails problemDetails = new ProblemDetails();
+        problemDetails.setDetail(etsiCatalogManagerBadRequestException.getMessage());
+        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(problemDetails);
+    }
+
+    @ExceptionHandler(SubscriptionNotFoundException.class)
+    public ResponseEntity<ProblemDetails> handleSubscriptionNotFoundException(
+            final SubscriptionNotFoundException subscriptionNotFoundException) {
+        final ProblemDetails problemDetails = new ProblemDetails();
+        problemDetails.setDetail(subscriptionNotFoundException.getMessage());
+        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problemDetails);
+    }
+
+    @ExceptionHandler(SubscriptionRequestConversionException.class)
+    public ResponseEntity<ProblemDetails> handleSubscriptionRequestConversionException(
+            final SubscriptionRequestConversionException subscriptionRequestConversionException) {
+        final ProblemDetails problemDetails = new ProblemDetails();
+        problemDetails.setDetail(subscriptionRequestConversionException.getMessage());
+        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(problemDetails);
+    }
+
     @ExceptionHandler(VnfPkgConflictException.class)
     public ResponseEntity<ProblemDetails> handleVnfPkgConflictException(
             final VnfPkgConflictException vnfPkgConflictException) {
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionNotFoundException.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionNotFoundException.java
new file mode 100644
index 0000000..58c2ef0
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionNotFoundException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============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.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an ETSI Catalog Manager Request Failure
+ * 
+ * @author gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.NOT_FOUND)
+public class SubscriptionNotFoundException extends RuntimeException {
+
+    private static final long serialVersionUID = 85268561453194516L;
+
+    public SubscriptionNotFoundException(final String message) {
+        super(message);
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return this;
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionRequestConversionException.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionRequestConversionException.java
new file mode 100644
index 0000000..daa544f
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/main/java/org/onap/so/adapters/vnfmadapter/rest/exceptions/SubscriptionRequestConversionException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============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.adapters.vnfmadapter.rest.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Exception for an ETSI Catalog Manager Request Failure
+ * 
+ * @author gareth.roper@est.tech
+ */
+@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
+public class SubscriptionRequestConversionException extends RuntimeException {
+
+    private static final long serialVersionUID = 45898561453196895L;
+
+    public SubscriptionRequestConversionException(final String message) {
+        super(message);
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        return this;
+    }
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionControllerTest.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionControllerTest.java
new file mode 100644
index 0000000..f90978e
--- /dev/null
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003PackageManagementSubscriptionControllerTest.java
@@ -0,0 +1,257 @@
+/*-
+ * ============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.adapters.vnfmadapter.rest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.onap.so.adapters.vnfmadapter.Constants.PACKAGE_MANAGEMENT_BASE_URL;
+import static org.onap.so.client.RestTemplateConfig.CONFIGURABLE_REST_TEMPLATE;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import java.security.GeneralSecurityException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+import com.google.gson.Gson;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.so.adapters.vnfmadapter.Constants;
+import org.onap.so.adapters.vnfmadapter.VnfmAdapterApplication;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.LinkSelf;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmNotificationsFilter;
+import org.onap.so.adapters.vnfmadapter.extclients.etsicatalog.model.PkgmSubscription;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.InlineResponse2002;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.PkgmSubscriptionRequest;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsAuthentication;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilter;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilter.NotificationTypesEnum;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsFilterVnfProductsFromProviders;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.SubscriptionsLinks;
+import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.VnfPackagesLinksSelf;
+import org.onap.so.utils.CryptoUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.client.MockRestServiceServer;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.http.HttpMethod;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
+import static org.hamcrest.Matchers.is;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+
+/**
+ * @author Ronan Kenny (ronan.kenny@est.tech)
+ * @author Gareth Roper (gareth.roper@est.tech)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = VnfmAdapterApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+@SuppressWarnings("unchecked")
+public class Sol003PackageManagementSubscriptionControllerTest {
+
+    private static String subscriptionId;
+    private final Gson gson = new Gson();
+
+    @Autowired
+    @Qualifier(CONFIGURABLE_REST_TEMPLATE)
+    private RestTemplate testRestTemplate;
+
+    private MockRestServiceServer mockRestServer;
+
+    @Autowired
+    private CacheManager cacheServiceProvider;
+    private final URI msbEndpoint = URI.create("http://msb-iag.onap:80/api/vnfpkgm/v1/subscriptions");
+
+    @Autowired
+    private Sol003PackageManagementSubscriptionController sol003PackageManagementSubscriptionController;
+
+    @Before
+    public void setUp() {
+        mockRestServer = MockRestServiceServer.bindTo(testRestTemplate).build();
+        final Cache cache = cacheServiceProvider.getCache(Constants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE);
+        cache.clear();
+    }
+
+    @Test
+    public void testSuccessPostSubscription() throws GeneralSecurityException, URISyntaxException {
+        final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
+        final ResponseEntity<InlineResponse2002> response =
+                (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+                        .postSubscriptionRequest(pkgmSubscriptionRequest);
+
+        final HttpHeaders headers = buildHttpHeaders(Objects.requireNonNull(response.getBody()).getCallbackUri());
+
+        SubscriptionsLinks subscriptionsLinks = new SubscriptionsLinks();
+        VnfPackagesLinksSelf vnfPackagesLinksSelf = new VnfPackagesLinksSelf();
+        vnfPackagesLinksSelf.setHref("https://so-vnfm-adapter.onap:30406" + PACKAGE_MANAGEMENT_BASE_URL
+                + "/subscriptions/" + response.getBody().getId());
+        subscriptionsLinks.setSelf(vnfPackagesLinksSelf);
+
+        assertEquals(pkgmSubscriptionRequest.getFilter(), response.getBody().getFilter());
+        assertEquals(subscriptionsLinks, response.getBody().getLinks());
+        assertEquals(response.getBody().getFilter(), pkgmSubscriptionRequest.getFilter());
+        assert (response.getHeaders().equals(headers));
+        assertThat(response.getStatusCode(), is(HttpStatus.CREATED));
+        assertNotNull(response.getBody().getCallbackUri());
+    }
+
+    @Test
+    public void testFailPostSubscriptionAlreadyExists() throws GeneralSecurityException {
+        final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
+
+        final ResponseEntity<InlineResponse2002> response =
+                (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+                        .postSubscriptionRequest(pkgmSubscriptionRequest);
+        subscriptionId = Objects.requireNonNull(response.getBody()).getId();
+
+        // Create duplicate entry
+        final PkgmSubscriptionRequest pkgmSubscriptionRequest2 = buildPkgmSubscriptionRequest();
+
+        final ResponseEntity<InlineResponse2002> response2002 =
+                (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+                        .postSubscriptionRequest(pkgmSubscriptionRequest2);
+
+        assertEquals(HttpStatus.SEE_OTHER, response2002.getStatusCode());
+    }
+
+    @Test
+    public void testSuccessGetSubscriptionWithSubscriptionId() throws GeneralSecurityException, URISyntaxException {
+        final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
+
+        final ResponseEntity<InlineResponse2002> response =
+                (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+                        .postSubscriptionRequest(pkgmSubscriptionRequest);
+        subscriptionId = Objects.requireNonNull(response.getBody()).getId();
+
+        final ResponseEntity<InlineResponse2002> response2002 =
+                (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+                        .getSubscription(subscriptionId);
+
+        final HttpHeaders headers = buildHttpHeaders(response.getBody().getCallbackUri());
+
+
+        assertEquals(response.getBody().getFilter(), pkgmSubscriptionRequest.getFilter());
+        assert (response.getHeaders().equals(headers));
+        assertEquals(HttpStatus.OK, response2002.getStatusCode());
+        assertEquals(pkgmSubscriptionRequest.getFilter(), response.getBody().getFilter());
+        // Ensure CallBackUri is set to new URI
+        assertNotEquals(pkgmSubscriptionRequest.getCallbackUri(), response.getBody().getCallbackUri());
+    }
+
+    @Test
+    public void testFailGetSubscriptionWithInvalidSubscriptionId() {
+        final ResponseEntity<InlineResponse2002> response =
+                (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
+                        .getSubscription("invalidSubscriptionId");
+        assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
+    }
+
+    @Test
+    public void testSuccessGetSubscriptions() throws GeneralSecurityException {
+        final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
+        final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
+
+        mockRestServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
+                .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
+
+        sol003PackageManagementSubscriptionController.postSubscriptionRequest(pkgmSubscriptionRequest);
+        ResponseEntity<List<InlineResponse2002>> response =
+                sol003PackageManagementSubscriptionController.getSubscriptions();
+
+        List<InlineResponse2002> subscriptionsList = response.getBody();
+
+        assertEquals(Objects.requireNonNull(response.getBody()).get(0).getFilter(),
+                pkgmSubscriptionRequest.getFilter());
+        assert (subscriptionsList != null);
+        assertNotEquals('0', subscriptionsList.size());
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+    }
+
+    private PkgmSubscriptionRequest buildPkgmSubscriptionRequest() {
+        final PkgmSubscriptionRequest pkgmSubscriptionRequest = new PkgmSubscriptionRequest();
+        final SubscriptionsFilter sub = buildSubscriptionsFilter();
+        final SubscriptionsAuthentication auth = new SubscriptionsAuthentication();
+        pkgmSubscriptionRequest.setFilter(sub);
+        pkgmSubscriptionRequest.setCallbackUri(msbEndpoint.toString());
+        pkgmSubscriptionRequest.setAuthentication(auth);
+        return pkgmSubscriptionRequest;
+    }
+
+    private SubscriptionsFilter buildSubscriptionsFilter() {
+        final SubscriptionsFilter sub = new SubscriptionsFilter();
+        final List<String> vnfdIdList = new ArrayList();
+        final List<String> vnfPkgIdList = new ArrayList();
+        final List<NotificationTypesEnum> notificationTypes = new ArrayList<>();
+        final SubscriptionsFilterVnfProductsFromProviders subscriptionsFilterVnfProductsFromProviders =
+                new SubscriptionsFilterVnfProductsFromProviders();
+        final List<SubscriptionsFilterVnfProductsFromProviders> vnfProductsFromProviders = new ArrayList<>();
+
+        vnfProductsFromProviders.add(subscriptionsFilterVnfProductsFromProviders);
+        sub.setVnfdId(vnfdIdList);
+        sub.setNotificationTypes(notificationTypes);
+        sub.setVnfPkgId(vnfPkgIdList);
+        sub.setVnfProductsFromProviders(vnfProductsFromProviders);
+        return sub;
+    }
+
+    private PkgmSubscription buildPkgmSubscription() {
+        PkgmSubscription pkgmSubscription = new PkgmSubscription();
+        PkgmNotificationsFilter pkgmNotificationsFilter = new PkgmNotificationsFilter();
+        LinkSelf linkSelf = new LinkSelf();
+        String id = UUID.randomUUID().toString();
+        pkgmSubscription.setId(id);
+        pkgmSubscription.setCallbackUri(msbEndpoint + "/" + pkgmSubscription.getId().toString());
+        pkgmSubscription.setFilter(pkgmNotificationsFilter);
+        pkgmSubscription.setLinks(linkSelf);
+        return pkgmSubscription;
+    }
+
+    private PkgmSubscriptionRequest postSubscriptionForTest() {
+        final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
+        final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
+
+        mockRestServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
+                .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
+        return pkgmSubscriptionRequest;
+    }
+
+    private HttpHeaders buildHttpHeaders(String uri) throws URISyntaxException {
+        final HttpHeaders headers = new HttpHeaders();
+        URI myUri = new URI(uri);
+        headers.setLocation(myUri);
+        return headers;
+    }
+
+}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003SubscriptionManagementControllerTest.java b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003SubscriptionManagementControllerTest.java
deleted file mode 100644
index ed18800..0000000
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/java/org/onap/so/adapters/vnfmadapter/rest/Sol003SubscriptionManagementControllerTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.onap.so.adapters.vnfmadapter.rest;
-
-import static org.junit.Assert.assertEquals;
-import static org.onap.so.client.RestTemplateConfig.CONFIGURABLE_REST_TEMPLATE;
-import java.net.URISyntaxException;
-import java.util.List;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.onap.so.adapters.vnfmadapter.VnfmAdapterApplication;
-import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.InlineResponse2002;
-import org.onap.so.adapters.vnfmadapter.extclients.vnfm.packagemanagement.model.PkgmSubscriptionRequest;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.test.web.client.MockRestServiceServer;
-import org.springframework.web.client.RestTemplate;
-
-/**
- * @author gareth.roper@est.tech
- */
-
-@RunWith(SpringRunner.class)
-@SpringBootTest(classes = VnfmAdapterApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@ActiveProfiles("test")
-public class Sol003SubscriptionManagementControllerTest {
-
-    private static final String subscriptionId = "mySubscriptionId";
-
-    @Autowired
-    @Qualifier(CONFIGURABLE_REST_TEMPLATE)
-    private RestTemplate testRestTemplate;
-
-    @Autowired
-    private Sol003SubscriptionManagementController controller;
-
-    @Before
-    public void setUp() throws Exception {
-        MockRestServiceServer.bindTo(testRestTemplate).build();
-    }
-
-    @Test
-    public void postSubscriptionRequest() throws URISyntaxException, InterruptedException {
-        final PkgmSubscriptionRequest pkgmSubscriptionRequest = new PkgmSubscriptionRequest();
-        final ResponseEntity<InlineResponse2002> response = controller.postSubscriptionRequest(pkgmSubscriptionRequest);
-        assertEquals(HttpStatus.NOT_IMPLEMENTED, response.getStatusCode());
-    }
-
-    @Test
-    public void getSubscriptions() throws URISyntaxException, InterruptedException {
-        final ResponseEntity<List<InlineResponse2002>> response = controller.getSubscriptions();
-        assertEquals(HttpStatus.NOT_IMPLEMENTED, response.getStatusCode());
-    }
-
-    @Test
-    public void deleteSubscription() throws URISyntaxException, InterruptedException {
-        final ResponseEntity<Void> response = controller.deleteSubscription(subscriptionId);
-        assertEquals(HttpStatus.NOT_IMPLEMENTED, response.getStatusCode());
-    }
-
-    @Test
-    public void getSubscription() throws URISyntaxException, InterruptedException {
-        final ResponseEntity<InlineResponse2002> response = controller.getSubscription(subscriptionId);
-        assertEquals(HttpStatus.NOT_IMPLEMENTED, response.getStatusCode());
-    }
-}
diff --git a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/resources/application.yaml b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/resources/application.yaml
index ae66464..cdb6662 100644
--- a/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/resources/application.yaml
+++ b/adapters/mso-vnfm-adapter/mso-vnfm-etsi-adapter/src/test/resources/application.yaml
@@ -40,6 +40,7 @@
 
 vnfmadapter:
   endpoint: https://so-vnfm-adapter.onap:30406
+
   
 #Actuator
 management:
diff --git a/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WaitForPnfReadyBB.bpmn b/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WaitForPnfReadyBB.bpmn
index b38ec69..29e2f2b 100644
--- a/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WaitForPnfReadyBB.bpmn
+++ b/bpmn/so-bpmn-building-blocks/src/main/resources/subprocess/BuildingBlock/WaitForPnfReadyBB.bpmn
@@ -8,20 +8,26 @@
     <bpmn:messageFlow id="MessageFlow_1py54jr" sourceRef="UnregisterfromPnfReadyEvent" targetRef="WorkflowMessageServiceForDmaap" />
   </bpmn:collaboration>
   <bpmn:process id="WaitForPnfReadyBB" name="WaitForPnfReadyBB" isExecutable="true">
-    <bpmn:startEvent id="WaitForPnfReady_StartEvent">
-      <bpmn:outgoing>SequenceFlow_1jzs6dp</bpmn:outgoing>
-    </bpmn:startEvent>
+    <bpmn:sequenceFlow id="SequenceFlow_17q5zqe" sourceRef="UpdatePnfOrchestrationStatusToRegistered" targetRef="AaiEntryUpdated" />
+    <bpmn:sequenceFlow id="SequenceFlow_0m2r6ye" sourceRef="UpdatePnfOrchestrationStatusToRegister" targetRef="WaitForDmaapPnfReadyNotification" />
+    <bpmn:sequenceFlow id="SequenceFlow_1miyzfe" sourceRef="UnregisterfromPnfReadyEvent" targetRef="ThrowTimeoutException" />
+    <bpmn:sequenceFlow id="SequenceFlow_0p09qgm" sourceRef="WaitForDmaapPnfReadyNotification" targetRef="UpdatePnfOrchestrationStatusToRegistered" />
+    <bpmn:sequenceFlow id="SequenceFlow_1o8od8e" sourceRef="RegisterForPnfReadyEvent" targetRef="UpdatePnfOrchestrationStatusToRegister" />
+    <bpmn:sequenceFlow id="SequenceFlow_1kc34bc" sourceRef="WaitForDmaapTimeout" targetRef="UnregisterfromPnfReadyEvent" />
+    <bpmn:sequenceFlow id="SequenceFlow_1jzs6dp" sourceRef="WaitForPnfReady_StartEvent" targetRef="RegisterForPnfReadyEvent" />
     <bpmn:serviceTask id="RegisterForPnfReadyEvent" name="Register for Pnf Ready Event" camunda:delegateExpression="${RegisterForPnfReadyEvent}">
       <bpmn:incoming>SequenceFlow_1jzs6dp</bpmn:incoming>
       <bpmn:outgoing>SequenceFlow_1o8od8e</bpmn:outgoing>
     </bpmn:serviceTask>
-    <bpmn:sequenceFlow id="SequenceFlow_1miyzfe" sourceRef="UnregisterfromPnfReadyEvent" targetRef="ThrowTimeoutException" />
-    <bpmn:sequenceFlow id="SequenceFlow_0p09qgm" sourceRef="WaitForDmaapPnfReadyNotification" targetRef="AaiEntryUpdated" />
-    <bpmn:sequenceFlow id="SequenceFlow_1o8od8e" sourceRef="RegisterForPnfReadyEvent" targetRef="WaitForDmaapPnfReadyNotification" />
-    <bpmn:sequenceFlow id="SequenceFlow_1kc34bc" sourceRef="WaitForDmaapTimeout" targetRef="UnregisterfromPnfReadyEvent" />
-    <bpmn:sequenceFlow id="SequenceFlow_1jzs6dp" sourceRef="WaitForPnfReady_StartEvent" targetRef="RegisterForPnfReadyEvent" />
-    <bpmn:receiveTask id="WaitForDmaapPnfReadyNotification" name="Wait for DMAAP pnf-ready notification" messageRef="Message_13h1tlo">
+    <bpmn:startEvent id="WaitForPnfReady_StartEvent">
+      <bpmn:outgoing>SequenceFlow_1jzs6dp</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:serviceTask id="UpdatePnfOrchestrationStatusToRegister" name="Update Pnf Orchestration Status to Register" camunda:expression="${AAIUpdateTasks.updateOrchestrationStatusRegisterPnf(InjectExecution.execute(execution, execution.getVariable(&#34;gBuildingBlockExecution&#34;)))}">
       <bpmn:incoming>SequenceFlow_1o8od8e</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_0m2r6ye</bpmn:outgoing>
+    </bpmn:serviceTask>
+    <bpmn:receiveTask id="WaitForDmaapPnfReadyNotification" name="Wait for DMAAP pnf-ready notification" messageRef="Message_13h1tlo">
+      <bpmn:incoming>SequenceFlow_0m2r6ye</bpmn:incoming>
       <bpmn:outgoing>SequenceFlow_0p09qgm</bpmn:outgoing>
     </bpmn:receiveTask>
     <bpmn:boundaryEvent id="WaitForDmaapTimeout" name="Timeout" attachedToRef="WaitForDmaapPnfReadyNotification">
@@ -30,17 +36,21 @@
         <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">#{timeoutForPnfEntryNotification}</bpmn:timeDuration>
       </bpmn:timerEventDefinition>
     </bpmn:boundaryEvent>
+    <bpmn:serviceTask id="UpdatePnfOrchestrationStatusToRegistered" name="Update Pnf Orchestration Status to Registered" camunda:expression="${AAIUpdateTasks.updateOrchestrationStatusRegisteredPnf(InjectExecution.execute(execution, execution.getVariable(&#34;gBuildingBlockExecution&#34;)))}">
+      <bpmn:incoming>SequenceFlow_0p09qgm</bpmn:incoming>
+      <bpmn:outgoing>SequenceFlow_17q5zqe</bpmn:outgoing>
+    </bpmn:serviceTask>
     <bpmn:serviceTask id="UnregisterfromPnfReadyEvent" name="Unregister from Pnf Ready Event" camunda:delegateExpression="${CancelDmaapSubscription}">
       <bpmn:incoming>SequenceFlow_1kc34bc</bpmn:incoming>
       <bpmn:outgoing>SequenceFlow_1miyzfe</bpmn:outgoing>
     </bpmn:serviceTask>
+    <bpmn:endEvent id="AaiEntryUpdated" name="AAI entry updated">
+      <bpmn:incoming>SequenceFlow_17q5zqe</bpmn:incoming>
+    </bpmn:endEvent>
     <bpmn:endEvent id="ThrowTimeoutException" name="Throw timeout exception">
       <bpmn:incoming>SequenceFlow_1miyzfe</bpmn:incoming>
       <bpmn:errorEventDefinition errorRef="Error_1" />
     </bpmn:endEvent>
-    <bpmn:endEvent id="AaiEntryUpdated" name="AAI entry updated">
-      <bpmn:incoming>SequenceFlow_0p09qgm</bpmn:incoming>
-    </bpmn:endEvent>
     <bpmn:textAnnotation id="TextAnnotation_1eyzes8">
       <bpmn:text>Inputs:
  - pnf name - String</bpmn:text>
@@ -52,12 +62,12 @@
   <bpmndi:BPMNDiagram id="BPMNDiagram_1">
     <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1d0w8lf">
       <bpmndi:BPMNShape id="Participant_1egg397_di" bpmnElement="WaitForPnfReadyBB_ID" isHorizontal="true">
-        <dc:Bounds x="160" y="50" width="810" height="400" />
+        <dc:Bounds x="160" y="50" width="1040" height="400" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="EndEvent_0k52gr7_di" bpmnElement="AaiEntryUpdated">
-        <dc:Bounds x="882" y="189" width="36" height="36" />
+        <dc:Bounds x="1112" y="189" width="36" height="36" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="858" y="230" width="88" height="14" />
+          <dc:Bounds x="1088" y="230" width="88" height="14" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="StartEvent_0j5ok9h_di" bpmnElement="WaitForPnfReady_StartEvent">
@@ -67,12 +77,12 @@
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="Participant_0vmrrhf_di" bpmnElement="WorkflowMessageServiceForDmaap" isHorizontal="true">
-        <dc:Bounds x="340" y="490" width="463" height="60" />
+        <dc:Bounds x="340" y="490" width="690" height="60" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="EndEvent_0wbx6tt_di" bpmnElement="ThrowTimeoutException">
-        <dc:Bounds x="882" y="322" width="36" height="36" />
+        <dc:Bounds x="1112" y="322" width="36" height="36" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="875" y="359" width="70" height="27" />
+          <dc:Bounds x="1105" y="359" width="70" height="27" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNShape id="TextAnnotation_1eyzes8_di" bpmnElement="TextAnnotation_1eyzes8">
@@ -83,32 +93,32 @@
         <di:waypoint x="237" y="109" />
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="MessageFlow_1vrcp2d_di" bpmnElement="MessageFlow_1vrcp2d">
-        <di:waypoint x="582" y="490" />
-        <di:waypoint x="582" y="247" />
+        <di:waypoint x="772" y="490" />
+        <di:waypoint x="772" y="247" />
         <bpmndi:BPMNLabel>
           <dc:Bounds x="996" y="380" width="90" height="10" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNShape id="BoundaryEvent_15eo1k9_di" bpmnElement="WaitForDmaapTimeout">
-        <dc:Bounds x="596" y="229" width="36" height="36" />
+        <dc:Bounds x="786" y="229" width="36" height="36" />
         <bpmndi:BPMNLabel>
-          <dc:Bounds x="639" y="240" width="40" height="14" />
+          <dc:Bounds x="829" y="240" width="40" height="14" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNShape>
       <bpmndi:BPMNEdge id="SequenceFlow_1kc34bc_di" bpmnElement="SequenceFlow_1kc34bc">
-        <di:waypoint x="614" y="265" />
-        <di:waypoint x="614" y="340" />
-        <di:waypoint x="710" y="340" />
+        <di:waypoint x="804" y="265" />
+        <di:waypoint x="804" y="340" />
+        <di:waypoint x="910" y="340" />
         <bpmndi:BPMNLabel>
           <dc:Bounds x="1028" y="309" width="90" height="10" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNShape id="ReceiveTask_1sfysua_di" bpmnElement="WaitForDmaapPnfReadyNotification">
-        <dc:Bounds x="530" y="167" width="100" height="80" />
+        <dc:Bounds x="720" y="167" width="100" height="80" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNEdge id="SequenceFlow_0p09qgm_di" bpmnElement="SequenceFlow_0p09qgm">
-        <di:waypoint x="630" y="207" />
-        <di:waypoint x="882" y="207" />
+        <di:waypoint x="820" y="207" />
+        <di:waypoint x="910" y="207" />
         <bpmndi:BPMNLabel>
           <dc:Bounds x="1106.5" y="187" width="90" height="10" />
         </bpmndi:BPMNLabel>
@@ -131,26 +141,40 @@
         <dc:Bounds x="340" y="167" width="100" height="80" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNEdge id="SequenceFlow_1miyzfe_di" bpmnElement="SequenceFlow_1miyzfe">
-        <di:waypoint x="810" y="340" />
-        <di:waypoint x="882" y="340" />
+        <di:waypoint x="1010" y="340" />
+        <di:waypoint x="1112" y="340" />
         <bpmndi:BPMNLabel>
           <dc:Bounds x="1233.5" y="343" width="90" height="10" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNEdge id="MessageFlow_1py54jr_di" bpmnElement="MessageFlow_1py54jr">
-        <di:waypoint x="760" y="380" />
-        <di:waypoint x="760" y="490" />
+        <di:waypoint x="960" y="380" />
+        <di:waypoint x="960" y="490" />
         <bpmndi:BPMNLabel>
           <dc:Bounds x="1165" y="458" width="90" height="10" />
         </bpmndi:BPMNLabel>
       </bpmndi:BPMNEdge>
       <bpmndi:BPMNShape id="ServiceTask_12j7hox_di" bpmnElement="UnregisterfromPnfReadyEvent">
-        <dc:Bounds x="710" y="300" width="100" height="80" />
+        <dc:Bounds x="910" y="300" width="100" height="80" />
       </bpmndi:BPMNShape>
       <bpmndi:BPMNEdge id="SequenceFlow_1jzs6dp_di" bpmnElement="SequenceFlow_1jzs6dp">
         <di:waypoint x="255" y="207" />
         <di:waypoint x="340" y="207" />
       </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="ServiceTask_1kiymc9_di" bpmnElement="UpdatePnfOrchestrationStatusToRegister">
+        <dc:Bounds x="530" y="167" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="SequenceFlow_0m2r6ye_di" bpmnElement="SequenceFlow_0m2r6ye">
+        <di:waypoint x="630" y="207" />
+        <di:waypoint x="720" y="207" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="SequenceFlow_17q5zqe_di" bpmnElement="SequenceFlow_17q5zqe">
+        <di:waypoint x="1010" y="207" />
+        <di:waypoint x="1112" y="207" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="ServiceTask_1e3i8pf_di" bpmnElement="UpdatePnfOrchestrationStatusToRegistered">
+        <dc:Bounds x="910" y="167" width="100" height="80" />
+      </bpmndi:BPMNShape>
     </bpmndi:BPMNPlane>
   </bpmndi:BPMNDiagram>
 </bpmn:definitions>
diff --git a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/aai/tasks/AAIUpdateTasks.java b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/aai/tasks/AAIUpdateTasks.java
index f1fbe54..dab3593 100644
--- a/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/aai/tasks/AAIUpdateTasks.java
+++ b/bpmn/so-bpmn-tasks/src/main/java/org/onap/so/bpmn/infrastructure/aai/tasks/AAIUpdateTasks.java
@@ -118,18 +118,35 @@
         }
     }
 
-
     /**
      * BPMN access method to update status of Pnf to Active in AAI
      *
      * @param execution
      */
     public void updateOrchestrationStatusActivePnf(BuildingBlockExecution execution) {
+        updateOrchestrationStatusForPnf(execution, OrchestrationStatus.ACTIVE);
+    }
+
+    /**
+     * BPMN access method to update status of Pnf to Register in AAI
+     */
+    public void updateOrchestrationStatusRegisterPnf(BuildingBlockExecution execution) {
+        updateOrchestrationStatusForPnf(execution, OrchestrationStatus.REGISTER);
+    }
+
+    /**
+     * BPMN access method to update status of Pnf to Registered in AAI
+     */
+    public void updateOrchestrationStatusRegisteredPnf(BuildingBlockExecution execution) {
+        updateOrchestrationStatusForPnf(execution, OrchestrationStatus.REGISTERED);
+    }
+
+    private void updateOrchestrationStatusForPnf(BuildingBlockExecution execution, OrchestrationStatus status) {
         try {
             Pnf pnf = extractPojosForBB.extractByKey(execution, ResourceKey.PNF);
-            aaiPnfResources.updateOrchestrationStatusPnf(pnf, OrchestrationStatus.ACTIVE);
+            aaiPnfResources.updateOrchestrationStatusPnf(pnf, status);
         } catch (Exception ex) {
-            logger.error("Exception occurred in AAIUpdateTasks updateOrchestrationStatusActivePnf", ex);
+            logger.error("Exception occurred in AAIUpdateTasks during update Orchestration Status to {}", status, ex);
             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
         }
     }
diff --git a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/aai/tasks/AAIUpdateTasksTest.java b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/aai/tasks/AAIUpdateTasksTest.java
index ae6dde6..19877aa 100644
--- a/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/aai/tasks/AAIUpdateTasksTest.java
+++ b/bpmn/so-bpmn-tasks/src/test/java/org/onap/so/bpmn/infrastructure/aai/tasks/AAIUpdateTasksTest.java
@@ -161,6 +161,26 @@
     }
 
     @Test
+    public void updateOrchestrationStatusRegisterPnfTest() throws Exception {
+        Pnf pnf = preparePnfAndExtractForPnf();
+        doNothing().when(aaiPnfResources).updateOrchestrationStatusPnf(pnf, OrchestrationStatus.REGISTER);
+
+        aaiUpdateTasks.updateOrchestrationStatusRegisterPnf(execution);
+
+        verify(aaiPnfResources, times(1)).updateOrchestrationStatusPnf(pnf, OrchestrationStatus.REGISTER);
+    }
+
+    @Test
+    public void updateOrchestrationStatusRegisteredPnfTest() throws Exception {
+        Pnf pnf = preparePnfAndExtractForPnf();
+        doNothing().when(aaiPnfResources).updateOrchestrationStatusPnf(pnf, OrchestrationStatus.REGISTERED);
+
+        aaiUpdateTasks.updateOrchestrationStatusRegisteredPnf(execution);
+
+        verify(aaiPnfResources, times(1)).updateOrchestrationStatusPnf(pnf, OrchestrationStatus.REGISTERED);
+    }
+
+    @Test
     public void updateOrchestrationStatusAssignedVnfTest() throws Exception {
         doNothing().when(aaiVnfResources).updateOrchestrationStatusVnf(genericVnf, OrchestrationStatus.ASSIGNED);
 
diff --git a/mso-catalog-db/src/main/java/org/onap/so/db/catalog/beans/OrchestrationStatus.java b/mso-catalog-db/src/main/java/org/onap/so/db/catalog/beans/OrchestrationStatus.java
index 9691eff..435c3a7 100644
--- a/mso-catalog-db/src/main/java/org/onap/so/db/catalog/beans/OrchestrationStatus.java
+++ b/mso-catalog-db/src/main/java/org/onap/so/db/catalog/beans/OrchestrationStatus.java
@@ -33,7 +33,9 @@
     PRECREATED("PreCreated", "pre.?created"),
     CONFIGASSIGNED("ConfigAssigned", "config.?assigned"),
     CONFIGURE("Configure", "configure"),
-    CONFIGURED("Configured", "configured");
+    CONFIGURED("Configured", "configured"),
+    REGISTER("Register", "register"),
+    REGISTERED("Registered", "registered");
 
     private final String name;
     private final String fuzzyMatcher;