Initial OpenECOMP MSO commit

Change-Id: Ia6a7574859480717402cc2f22534d9973a78fa6d
Signed-off-by: ChrisC <cc697w@intl.att.com>
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/ASDCControllerSingleton.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/ASDCControllerSingleton.java
new file mode 100644
index 0000000..d8ac7d6
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/ASDCControllerSingleton.java
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc;
+
+
+import javax.annotation.PreDestroy;
+import javax.ejb.ConcurrencyManagement;
+import javax.ejb.ConcurrencyManagementType;
+import javax.ejb.Lock;
+import javax.ejb.LockType;
+import javax.ejb.Schedule;
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+
+import org.openecomp.mso.asdc.client.ASDCGlobalController;
+import org.openecomp.mso.logger.MsoLogger;
+
+@Singleton(name = "ASDCController")
+@Lock(LockType.READ)
+@Startup
+@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
+public class ASDCControllerSingleton {
+
+    private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.ASDC);
+    private static boolean working = false;
+
+    private ASDCGlobalController globalController = new ASDCGlobalController ();
+
+    /**
+     * Main Constructor of the ASDC Singleton
+     */
+    public ASDCControllerSingleton () {
+    }
+
+    @Schedule(second ="30", minute = "*", hour = "*", persistent = false)
+    public void periodicControllerTask () {
+        if (isWorking ()) {
+            LOGGER.debug ("Another thread is already trying to init ASDC, cancel this periodic call");
+            return;
+        }
+        try {
+            setWorking (true);
+            
+            globalController.updateControllersConfigIfNeeded();
+            globalController.checkInStoppedState();
+
+        } finally {
+            setWorking (false);
+        }
+    }
+
+    @PreDestroy
+    private void terminate () {
+        globalController.closeASDC ();
+    }
+
+    private static synchronized boolean isWorking () {
+        return ASDCControllerSingleton.working;
+    }
+
+    private static synchronized void setWorking (boolean working) {
+        ASDCControllerSingleton.working = working;
+    }
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCConfiguration.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCConfiguration.java
new file mode 100644
index 0000000..1d87ccb
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCConfiguration.java
@@ -0,0 +1,418 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.codehaus.jackson.JsonNode;
+
+import org.openecomp.sdc.api.consumer.IConfiguration;
+import org.openecomp.mso.asdc.client.exceptions.ASDCParametersException;
+import org.openecomp.mso.properties.MsoJsonProperties;
+import org.openecomp.mso.properties.MsoPropertiesException;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+public class ASDCConfiguration implements IConfiguration {
+
+    private MsoPropertiesFactory msoPropertiesFactory;
+
+    // SHell command to obtain the same encryption, 128 bits key, key must be HEX
+    // echo -n "This is a test string" | openssl aes-128-ecb -e -K 546573746F736973546573746F736973 -nosalt | xxd
+
+    private String configKey;
+
+    private MsoJsonProperties msoProperties;
+
+    private String asdcControllerName;
+
+    public static final String MSO_PROP_ASDC = "MSO_PROP_ASDC";
+    public static final String PARAMETER_PATTERN = "asdc-connections";
+
+    public static final String CONSUMER_GROUP_ATTRIBUTE_NAME = "consumerGroup";
+    public static final String CONSUMER_ID_ATTRIBUTE_NAME = "consumerId";
+    public static final String ENVIRONMENT_NAME_ATTRIBUTE_NAME = "environmentName";
+    public static final String PASSWORD_ATTRIBUTE_NAME = "password";
+    public static final String POLLING_INTERVAL_ATTRIBUTE_NAME = "pollingInterval";
+    public static final String RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME = "relevantArtifactTypes";
+    public static final String USER_ATTRIBUTE_NAME = "user";
+    public static final String ASDC_ADDRESS_ATTRIBUTE_NAME = "asdcAddress";
+    public static final String POLLING_TIMEOUT_ATTRIBUTE_NAME = "pollingTimeout";
+    public static final String ACTIVATE_SERVER_TLS_AUTH = "activateServerTLSAuth";
+    public static final String KEY_STORE_PASSWORD = "keyStorePassword";
+    public static final String KEY_STORE_PATH = "keyStorePath";
+
+    public static final String HEAT="HEAT";
+    public static final String HEAT_ARTIFACT="HEAT_ARTIFACT";
+    public static final String HEAT_ENV="HEAT_ENV";
+    public static final String HEAT_NESTED="HEAT_NESTED";
+    public static final String HEAT_NET="HEAT_NET";
+    public static final String HEAT_VOL="HEAT_VOL";
+    public static final String OTHER="OTHER";
+    public static final String VF_MODULES_METADATA="VF_MODULES_METADATA";
+    
+    
+    private static final String[] SUPPORTED_ARTIFACT_TYPES = {HEAT,
+    		HEAT_ARTIFACT,
+    		HEAT_ENV,
+    		HEAT_NESTED,
+    		HEAT_NET,
+    		HEAT_VOL,
+    		OTHER,
+    		VF_MODULES_METADATA};   
+    
+    public static final List<String>  SUPPORTED_ARTIFACT_TYPES_LIST =  Collections.unmodifiableList(Arrays.asList(SUPPORTED_ARTIFACT_TYPES));   
+    
+    /**
+     * Default constructor, the mso.properties is searched in the classpath (for testing)
+     * Or in /etc/ecomp/mso/config/mso.properties
+     *
+     * @param controllerName The controllerName of the config JSON tree
+     * @throws ASDCParametersException in case of issues with the parameters
+     * @throws IOException If the key file has not been loaded properly
+     */
+    public ASDCConfiguration (String controllerName) throws ASDCParametersException, IOException {
+    	
+        Properties keyProp = new Properties ();
+        this.asdcControllerName = controllerName;
+
+        keyProp.load (Thread.currentThread ().getContextClassLoader ().getResourceAsStream ("config-key.properties"));
+        configKey = (String) keyProp.get ("asdc.config.key");
+
+        // This structure contains static values initialized by servlet initializer
+        this.msoPropertiesFactory = new MsoPropertiesFactory ();
+
+        refreshASDCConfig ();
+
+    }
+
+    public String getAsdcControllerName () {
+        return asdcControllerName;
+    }
+
+    private JsonNode getASDCControllerConfigJsonNode () {
+        if (this.msoProperties.getJsonRootNode ().get (PARAMETER_PATTERN) != null) {
+            return this.msoProperties.getJsonRootNode ().get (PARAMETER_PATTERN).get (this.asdcControllerName);
+        } else {
+            return null;
+        }
+
+    }
+
+    /**
+     * This method reload the config if needed.
+     *
+     * @return true if config has been reloaded, false otherwise
+     * @throws ASDCParametersException In case the parameters validation fails
+     * @throws MsoPropertiesException
+     */
+    public boolean refreshASDCConfig () throws ASDCParametersException {
+
+        try {
+            if (msoPropertiesFactory.propertiesHaveChanged (MSO_PROP_ASDC, msoProperties)) {
+                msoProperties = msoPropertiesFactory.getMsoJsonProperties (MSO_PROP_ASDC);
+
+                this.testAllParameters ();
+                return true;
+            } else {
+                return false;
+            }
+        } catch (MsoPropertiesException e) {
+            throw new ASDCParametersException ("mso.asdc.json not initialized properly, ASDC config cannot be reloaded",
+                                               e);
+        }
+    }
+
+    /**
+     * This method is useful to check whether a mso properties config has been changed.
+     *
+     * @return true is a new config is availabe, false otherwise
+     * @throws ASDCParametersException
+     * @throws MsoPropertiesException
+     */
+    public boolean hasASDCConfigChanged () throws ASDCParametersException {
+        try {
+            return msoPropertiesFactory.propertiesHaveChanged (MSO_PROP_ASDC, msoProperties);
+        } catch (MsoPropertiesException e) {
+            throw new ASDCParametersException ("mso.asdc.json not initialized properly, ASDC config cannot be read", e);
+        }
+    }
+
+    @Override
+    public String getConsumerGroup () {
+        JsonNode masterConfigNode = getASDCControllerConfigJsonNode ();
+        if (masterConfigNode != null && masterConfigNode.get (CONSUMER_GROUP_ATTRIBUTE_NAME) != null) {
+            String config = masterConfigNode.get (CONSUMER_GROUP_ATTRIBUTE_NAME).asText ();
+
+            if ("NULL".equals (config) || config.isEmpty ()) {
+                return null;
+            } else {
+                return config;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public String getConsumerID () {
+
+        JsonNode masterConfigNode = getASDCControllerConfigJsonNode ();
+        if (masterConfigNode != null && masterConfigNode.get (CONSUMER_ID_ATTRIBUTE_NAME) != null) {
+            String config = masterConfigNode.get (CONSUMER_ID_ATTRIBUTE_NAME).asText ();
+
+            if (config.isEmpty ()) {
+                return null;
+            } else {
+                return config;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public String getEnvironmentName () {
+        JsonNode masterConfigNode = getASDCControllerConfigJsonNode ();
+        if (masterConfigNode != null && masterConfigNode.get (ENVIRONMENT_NAME_ATTRIBUTE_NAME) != null) {
+            String config = masterConfigNode.get (ENVIRONMENT_NAME_ATTRIBUTE_NAME).asText ();
+
+            if (config.isEmpty ()) {
+                return null;
+            } else {
+                return config;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public String getPassword () {
+        JsonNode masterConfigNode = getASDCControllerConfigJsonNode ();
+        if (masterConfigNode != null && masterConfigNode.get (PASSWORD_ATTRIBUTE_NAME) != null) {
+            String config = this.msoProperties.getEncryptedProperty (masterConfigNode.get (PASSWORD_ATTRIBUTE_NAME),
+                                                                     null,
+                                                                     this.configKey);
+
+            if (config.isEmpty ()) {
+                return null;
+            } else {
+                return config;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public int getPollingInterval () {
+        JsonNode masterConfigNode = getASDCControllerConfigJsonNode ();
+        if (masterConfigNode != null && masterConfigNode.get (POLLING_INTERVAL_ATTRIBUTE_NAME) != null) {
+            return masterConfigNode.get (POLLING_INTERVAL_ATTRIBUTE_NAME).asInt ();
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public List <String> getRelevantArtifactTypes () {
+    	// DO not return the Static List SUPPORTED_ARTIFACT_TYPES_LIST because the ASDC Client will try to modify it !!!
+    	return Arrays.asList(SUPPORTED_ARTIFACT_TYPES);
+    }
+
+    @Override
+    public String getUser () {
+        JsonNode masterConfigNode = getASDCControllerConfigJsonNode ();
+        if (masterConfigNode != null && masterConfigNode.get (USER_ATTRIBUTE_NAME) != null) {
+            String config = masterConfigNode.get (USER_ATTRIBUTE_NAME).asText ();
+
+            if (config.isEmpty ()) {
+                return null;
+            } else {
+                return config;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public String getAsdcAddress () {
+        JsonNode masterConfigNode = getASDCControllerConfigJsonNode ();
+        if (masterConfigNode != null && masterConfigNode.get (ASDC_ADDRESS_ATTRIBUTE_NAME) != null) {
+            String config = masterConfigNode.get (ASDC_ADDRESS_ATTRIBUTE_NAME).asText ();
+
+            if (config.isEmpty ()) {
+                return null;
+            } else {
+                return config;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public int getPollingTimeout () {
+        JsonNode masterConfigNode = getASDCControllerConfigJsonNode ();
+        if (masterConfigNode != null && masterConfigNode.get (POLLING_TIMEOUT_ATTRIBUTE_NAME) != null) {
+            return masterConfigNode.get (POLLING_TIMEOUT_ATTRIBUTE_NAME).asInt ();
+        } else {
+            return 0;
+        }
+    }
+    
+	@Override
+	public boolean activateServerTLSAuth() {
+		JsonNode masterConfigNode = getASDCControllerConfigJsonNode();
+		if (masterConfigNode != null && masterConfigNode.get(ACTIVATE_SERVER_TLS_AUTH) != null) {
+			return masterConfigNode.get(ACTIVATE_SERVER_TLS_AUTH).asBoolean(false);
+		} else {
+			return false;
+		}
+	}
+
+	@Override
+	public String getKeyStorePassword() {
+		JsonNode masterConfigNode = getASDCControllerConfigJsonNode();
+		if (masterConfigNode != null && masterConfigNode.get(KEY_STORE_PASSWORD) != null) {
+			String config = this.msoProperties.getEncryptedProperty(masterConfigNode.get(KEY_STORE_PASSWORD), null,
+					this.configKey);
+
+			if (config.isEmpty()) {
+				return null;
+			} else {
+				return config;
+			}
+		} else {
+			return null;
+		}
+	}
+
+	@Override
+	public String getKeyStorePath() {
+		JsonNode masterConfigNode = getASDCControllerConfigJsonNode();
+		if (masterConfigNode != null && masterConfigNode.get(KEY_STORE_PATH) != null) {
+			String config = masterConfigNode.get(KEY_STORE_PATH).asText();
+
+			if (config.isEmpty()) {
+				return null;
+			} else {
+				return config;
+			}
+		} else {
+			return null;
+		}
+	}
+
+    public void testAllParameters () throws ASDCParametersException {
+
+        // Special case for this attribute that can be null from getConsumerGroup
+        if (this.getConsumerGroup () == null
+            && (getASDCControllerConfigJsonNode () == null
+                || !"NULL".equals (getASDCControllerConfigJsonNode ().get (CONSUMER_GROUP_ATTRIBUTE_NAME).asText ()))) {
+            throw new ASDCParametersException (CONSUMER_GROUP_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+
+        if (this.getConsumerID () == null || this.getConsumerID ().isEmpty ()) {
+            throw new ASDCParametersException (CONSUMER_ID_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+
+        if (this.getEnvironmentName () == null || this.getEnvironmentName ().isEmpty ()) {
+            throw new ASDCParametersException (ENVIRONMENT_NAME_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+
+        if (this.getAsdcAddress () == null || this.getAsdcAddress ().isEmpty ()) {
+            throw new ASDCParametersException (ASDC_ADDRESS_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+
+        if (this.getPassword () == null || this.getPassword ().isEmpty ()) {
+            throw new ASDCParametersException (PASSWORD_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+
+        if (this.getPollingInterval () == 0) {
+            throw new ASDCParametersException (POLLING_INTERVAL_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+
+        if (this.getPollingTimeout () == 0) {
+            throw new ASDCParametersException (POLLING_TIMEOUT_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+
+        if (this.getRelevantArtifactTypes () == null || this.getRelevantArtifactTypes ().isEmpty ()) {
+            throw new ASDCParametersException (RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+
+        if (this.getUser () == null || this.getUser ().isEmpty ()) {
+            throw new ASDCParametersException (USER_ATTRIBUTE_NAME
+                                               + " parameter cannot be found in config mso.properties");
+        }
+    }
+
+    /**
+     * This method triggers the MsoPropertiesFactory to get the ASDC config from the cache and extracts all controllers
+     * defined.
+     *
+     * @return A list of controller Names defined in the cache config
+     * @throws ASDCParametersException In cas of issues with the cache
+     */
+    public static List <String> getAllDefinedControllers () throws ASDCParametersException {
+
+        MsoJsonProperties msoProp;
+        try {
+            List <String> result = new ArrayList <String> ();
+            msoProp = new MsoPropertiesFactory ().getMsoJsonProperties (MSO_PROP_ASDC);
+
+            if (msoProp.getJsonRootNode ().get (PARAMETER_PATTERN) != null) {
+                Iterator <Entry <String, JsonNode>> it = msoProp.getJsonRootNode ()
+                                                                .get (PARAMETER_PATTERN)
+                                                                .getFields ();
+
+                Entry <String, JsonNode> entry;
+                while (it.hasNext ()) {
+                    entry = it.next ();
+                    result.add (entry.getKey ());
+
+                }
+            }
+            return result;
+        } catch (MsoPropertiesException e) {
+            throw new ASDCParametersException ("Unable to get the JSON Properties in cache:" + MSO_PROP_ASDC, e);
+        }
+
+    }
+
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCController.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCController.java
new file mode 100644
index 0000000..b553100
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCController.java
@@ -0,0 +1,570 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client;
+
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import org.openecomp.sdc.api.IDistributionClient;
+import org.openecomp.sdc.api.consumer.IDistributionStatusMessage;
+import org.openecomp.sdc.api.consumer.INotificationCallback;
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.sdc.api.notification.INotificationData;
+import org.openecomp.sdc.api.notification.IResourceInstance;
+import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
+import org.openecomp.sdc.api.results.IDistributionClientResult;
+import org.openecomp.sdc.impl.DistributionClientFactory;
+import org.openecomp.sdc.utils.DistributionActionResultEnum;
+import org.openecomp.sdc.utils.DistributionStatusEnum;
+import org.openecomp.mso.asdc.client.exceptions.ASDCControllerException;
+import org.openecomp.mso.asdc.client.exceptions.ASDCDownloadException;
+import org.openecomp.mso.asdc.client.exceptions.ASDCParametersException;
+import org.openecomp.mso.asdc.client.exceptions.ArtifactInstallerException;
+import org.openecomp.mso.asdc.installer.IVfResourceInstaller;
+import org.openecomp.mso.asdc.installer.VfResourceStructure;
+import org.openecomp.mso.asdc.installer.heat.VfResourceInstaller;
+import org.openecomp.mso.asdc.util.ASDCNotificationLogging;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoAlarmLogger;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.utils.UUIDChecker;
+
+public class ASDCController {
+
+    protected static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.ASDC);
+
+    protected static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
+
+    protected boolean isAsdcClientAutoManaged = false;
+
+    protected String controllerName;
+
+    /**
+     * Inner class for Notification callback
+     *
+     *
+     */
+    private final class ASDCNotificationCallBack implements INotificationCallback {
+
+        private ASDCController asdcController;
+
+        ASDCNotificationCallBack (ASDCController controller) {
+            asdcController = controller;
+        }
+
+        /**
+         * This method can be called multiple times at the same moment.
+         * The controller must be thread safe !
+         */
+        @Override
+        public void activateCallback (INotificationData iNotif) {
+            long startTime = System.currentTimeMillis ();
+            UUIDChecker.generateUUID (LOGGER);
+            MsoLogger.setServiceName ("NotificationHandler");
+            MsoLogger.setLogContext (iNotif.getDistributionID (), iNotif.getServiceUUID ());
+            String event = "Receive a callback notification in ASDC, nb of resources: " + iNotif.getResources ().size ();
+            LOGGER.debug(event);
+            asdcController.treatNotification (iNotif);
+            LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Completed the treatment of the notification");
+        }
+    }
+
+    // ***** Controller STATUS code
+
+    protected int nbOfNotificationsOngoing = 0;
+
+    public int getNbOfNotificationsOngoing () {
+        return nbOfNotificationsOngoing;
+    }
+
+    private ASDCControllerStatus controllerStatus = ASDCControllerStatus.STOPPED;
+
+    protected synchronized final void changeControllerStatus (ASDCControllerStatus newControllerStatus) {
+        switch (newControllerStatus) {
+
+            case BUSY:
+                ++this.nbOfNotificationsOngoing;
+                this.controllerStatus = newControllerStatus;
+                break;
+
+            case IDLE:
+                if (this.nbOfNotificationsOngoing > 1) {
+                    --this.nbOfNotificationsOngoing;
+                } else {
+                    this.nbOfNotificationsOngoing = 0;
+                    this.controllerStatus = newControllerStatus;
+                }
+
+                break;
+            default:
+                this.controllerStatus = newControllerStatus;
+                break;
+
+        }
+    }
+
+    public synchronized final ASDCControllerStatus getControllerStatus () {
+        return this.controllerStatus;
+    }
+
+    // ***** END of Controller STATUS code
+
+    protected ASDCConfiguration asdcConfig;
+    private IDistributionClient distributionClient;
+    private IVfResourceInstaller resourceInstaller;
+
+    public ASDCController (String controllerConfigName) {
+        isAsdcClientAutoManaged = true;
+        this.controllerName = controllerConfigName;
+        this.resourceInstaller = new VfResourceInstaller();
+    }
+
+    public ASDCController (String controllerConfigName, IDistributionClient asdcClient, IVfResourceInstaller resourceinstaller) {
+
+        distributionClient = asdcClient;
+        this.resourceInstaller = resourceinstaller;
+        this.controllerName = controllerConfigName;
+    }
+
+    public ASDCController (String controllerConfigName,IDistributionClient asdcClient) {
+        distributionClient = asdcClient;
+        this.controllerName = controllerConfigName;
+        this.resourceInstaller = new VfResourceInstaller();
+    }
+
+    /**
+     * This method refresh the ASDC Controller config and restart the client.
+     *
+     * @return true if config has been reloaded, false otherwise
+     * @throws ASDCControllerException If case of issue with the init or close called during the config reload
+     * @throws ASDCParametersException If there is an issue with the parameters
+     * @throws IOException In case of the key file could not be loaded properly
+     */
+    public boolean updateConfigIfNeeded () throws ASDCParametersException, ASDCControllerException, IOException {
+        LOGGER.debug ("Checking whether ASDC config must be reloaded");
+
+        try {
+            if (this.asdcConfig != null && this.asdcConfig.hasASDCConfigChanged ()) {
+                LOGGER.debug ("ASDC Config must be reloaded");
+                this.closeASDC ();
+                this.asdcConfig.refreshASDCConfig ();
+                this.initASDC ();
+                return true;
+            } else {
+                LOGGER.debug ("ASDC Config must NOT be reloaded");
+                return false;
+            }
+        } catch (ASDCParametersException ep) {
+            // Try to close it at least to make it consistent with the file specified
+            // We cannot let it run with a different config file, even if it's bad.
+            // This call could potentially throw a ASDCController exception if the controller is currently BUSY.
+            this.closeASDC ();
+
+            throw ep;
+        }
+    }
+
+    /**
+     * This method initializes the ASDC Controller and the ASDC Client.
+     *
+     * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be instantiated or if an init
+     *         attempt is done when already initialized
+     * @throws ASDCParametersException If there is an issue with the parameters provided
+     * @throws IOException In case of issues when trying to load the key file
+     */
+    public void initASDC () throws ASDCControllerException, ASDCParametersException, IOException {
+        String event = "Initialize the ASDC Controller";
+        MsoLogger.setServiceName ("InitASDC");
+        LOGGER.debug (event);
+        if (this.getControllerStatus () != ASDCControllerStatus.STOPPED) {
+            String endEvent = "The controller is already initialized, call the closeASDC method first";
+            throw new ASDCControllerException (endEvent);
+        }
+
+        if (asdcConfig == null) {
+            asdcConfig = new ASDCConfiguration (this.controllerName);
+
+        }
+        // attempt to refresh during init as MsoProperties is may be pointing to an old file
+        // Be careful this is static in MsoProperties
+        asdcConfig.refreshASDCConfig ();
+
+        if (this.distributionClient == null) {
+            distributionClient = DistributionClientFactory.createDistributionClient ();
+        }
+        long initStartTime = System.currentTimeMillis ();
+        IDistributionClientResult result = this.distributionClient.init (asdcConfig,
+                                                                         new ASDCNotificationCallBack (this));
+        if (!result.getDistributionActionResult ().equals (DistributionActionResultEnum.SUCCESS)) {
+            String endEvent = "ASDC distribution client init failed with reason:"
+                              + result.getDistributionMessageResult ();
+            LOGGER.recordMetricEvent (initStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, "Initialization of the ASDC Controller failed with reason:" + result.getDistributionMessageResult (), "ASDC", "init", null);
+            LOGGER.debug (endEvent);
+            asdcConfig = null;
+
+            this.changeControllerStatus (ASDCControllerStatus.STOPPED);
+            throw new ASDCControllerException ("Initialization of the ASDC Controller failed with reason: "
+                                               + result.getDistributionMessageResult ());
+        }
+        LOGGER.recordMetricEvent (initStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully initialize ASDC Controller", "ASDC", "init", null);
+
+        long clientstartStartTime = System.currentTimeMillis ();
+        result = this.distributionClient.start ();
+        if (!result.getDistributionActionResult ().equals (DistributionActionResultEnum.SUCCESS)) {
+            String endEvent = "ASDC distribution client start failed with reason:"
+                              + result.getDistributionMessageResult ();
+            LOGGER.recordMetricEvent (clientstartStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, endEvent, "ASDC", "start", null);
+            LOGGER.debug (endEvent);
+            asdcConfig = null;
+            this.changeControllerStatus (ASDCControllerStatus.STOPPED);
+            throw new ASDCControllerException ("Startup of the ASDC Controller failed with reason: "
+                                               + result.getDistributionMessageResult ());
+        }
+        LOGGER.recordMetricEvent (clientstartStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully start ASDC distribution client", "ASDC", "start", null);
+
+
+        this.changeControllerStatus (ASDCControllerStatus.IDLE);
+        LOGGER.info (MessageEnum.ASDC_INIT_ASDC_CLIENT_SUC, "ASDC", "changeControllerStatus");
+    }
+
+    /**
+     * This method closes the ASDC Controller and the ASDC Client.
+     *
+     * @throws ASDCControllerException It throws an exception if the ASDC Client cannot be closed because
+     *         it's currently BUSY in processing notifications.
+     */
+    public void closeASDC () throws ASDCControllerException {
+
+        MsoLogger.setServiceName ("CloseController");
+        if (this.getControllerStatus () == ASDCControllerStatus.BUSY) {
+            throw new ASDCControllerException ("Cannot close the ASDC controller as it's currently in BUSY state");
+        }
+        if (this.distributionClient != null) {
+            this.distributionClient.stop ();
+            // If auto managed we can set it to Null, ASDCController controls it.
+            // In the other case the client of this class has specified it, so we can't reset it
+            if (isAsdcClientAutoManaged) {
+                // Next init will initialize it with a new ASDC Client
+                this.distributionClient = null;
+            }
+
+        }
+        this.changeControllerStatus (ASDCControllerStatus.STOPPED);
+    }
+
+    private boolean checkResourceAlreadyDeployed (VfResourceStructure vfResource) throws ArtifactInstallerException {
+
+    	if (this.resourceInstaller.isResourceAlreadyDeployed (vfResource)) {
+            LOGGER.info (MessageEnum.ASDC_ARTIFACT_ALREADY_EXIST,
+            			vfResource.getResourceInstance().getResourceInstanceName(),
+            			vfResource.getResourceInstance().getResourceUUID(),
+            			vfResource.getResourceInstance().getResourceName(), "", "");
+            
+            this.sendDeployNotificationsForResource(vfResource,DistributionStatusEnum.ALREADY_DOWNLOADED,null);
+            this.sendDeployNotificationsForResource(vfResource,DistributionStatusEnum.ALREADY_DEPLOYED,null);
+           
+            return true;
+        } else {
+            return false;
+        }
+
+    }
+
+    private final static String UUID_PARAM = "(UUID:";
+    
+    private IDistributionClientDownloadResult downloadTheArtifact (IArtifactInfo artifact,
+                                                                   String distributionId) throws ASDCDownloadException {
+
+        LOGGER.debug ("Trying to download the artifact : " + artifact.getArtifactURL ()
+                      + UUID_PARAM
+                      + artifact.getArtifactUUID ()
+                      + ")");
+        IDistributionClientDownloadResult downloadResult;
+
+       
+        try {
+            downloadResult = distributionClient.download (artifact);
+            if (null == downloadResult) {
+            	LOGGER.info (MessageEnum.ASDC_ARTIFACT_NULL, artifact.getArtifactUUID (), "", "");
+            	return downloadResult;
+            }
+        } catch (RuntimeException e) {
+            LOGGER.debug ("Not able to download the artifact due to an exception: " + artifact.getArtifactURL ());
+            this.sendASDCNotification (NotificationType.DOWNLOAD,
+                                       artifact.getArtifactURL (),
+                                       asdcConfig.getConsumerID (),
+                                       distributionId,
+                                       DistributionStatusEnum.DOWNLOAD_ERROR,
+                                       e.getMessage (),
+                                       System.currentTimeMillis ());
+
+            throw new ASDCDownloadException ("Exception caught when downloading the artifact", e);
+        }
+
+        if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult ())) {
+
+            LOGGER.info (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_SUC,
+                         artifact.getArtifactURL (),
+                         artifact.getArtifactUUID (),
+                         String.valueOf (downloadResult.getArtifactPayload ().length), "", "");
+
+        } else {
+
+            LOGGER.error (MessageEnum.ASDC_ARTIFACT_DOWNLOAD_FAIL,
+                          artifact.getArtifactName (),
+                          artifact.getArtifactURL (),
+                          artifact.getArtifactUUID (),
+                          downloadResult.getDistributionMessageResult (), "", "", MsoLogger.ErrorCode.DataError, "ASDC artifact download fail");
+
+            this.sendASDCNotification (NotificationType.DOWNLOAD,
+                                       artifact.getArtifactURL (),
+                                       asdcConfig.getConsumerID (),
+                                       distributionId,
+                                       DistributionStatusEnum.DOWNLOAD_ERROR,
+                                       downloadResult.getDistributionMessageResult (),
+                                       System.currentTimeMillis ());
+
+            throw new ASDCDownloadException ("Artifact " + artifact.getArtifactName ()
+                                             + " could not be downloaded from ASDC URL "
+                                             + artifact.getArtifactURL ()
+                                             + UUID_PARAM
+                                             + artifact.getArtifactUUID ()
+                                             + ")"
+                                             + System.lineSeparator ()
+                                             + "Error message is "
+                                             + downloadResult.getDistributionMessageResult ()
+                                             + System.lineSeparator ());
+
+        }
+
+        this.sendASDCNotification (NotificationType.DOWNLOAD,
+                                   artifact.getArtifactURL (),
+                                   asdcConfig.getConsumerID (),
+                                   distributionId,
+                                   DistributionStatusEnum.DOWNLOAD_OK,
+                                   null,
+                                   System.currentTimeMillis ());
+        return downloadResult;
+
+    }
+
+   
+    private void sendDeployNotificationsForResource(VfResourceStructure vfResourceStructure,DistributionStatusEnum distribStatus, String errorReason) {
+    
+    	for (IArtifactInfo artifactInfo : vfResourceStructure.getResourceInstance().getArtifacts()) {
+    	
+    		if (DistributionStatusEnum.DEPLOY_OK.equals(distribStatus) 
+    				// This could be NULL if the artifact is a VF module artifact, this won't be present in the MAP
+    				&& vfResourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()) != null 
+    				&& vfResourceStructure.getArtifactsMapByUUID().get(artifactInfo.getArtifactUUID()).getDeployedInDb() == 0) {
+    			this.sendASDCNotification (NotificationType.DEPLOY,
+	    				artifactInfo.getArtifactURL (),
+	                  asdcConfig.getConsumerID (),
+	                  vfResourceStructure.getNotification().getDistributionID(),
+	                  DistributionStatusEnum.DEPLOY_ERROR,
+	                  "The artifact has not been used by the modules defined in the resource",
+	                  System.currentTimeMillis ());
+    		} else {
+	    		this.sendASDCNotification (NotificationType.DEPLOY,
+	    				artifactInfo.getArtifactURL (),
+	                  asdcConfig.getConsumerID (),
+	                  vfResourceStructure.getNotification().getDistributionID(),
+	                  distribStatus,
+	                  errorReason,
+	                  System.currentTimeMillis ());
+    		}
+    	}
+    }
+    
+    private void deployResourceStructure (VfResourceStructure vfResourceStructure) throws ArtifactInstallerException {
+
+    	LOGGER.info (MessageEnum.ASDC_START_DEPLOY_ARTIFACT, vfResourceStructure.getResourceInstance().getResourceInstanceName(), vfResourceStructure.getResourceInstance().getResourceUUID(), "ASDC", "deployResourceStructure");
+        try {
+        	vfResourceStructure.createVfModuleStructures();
+        	resourceInstaller.installTheResource (vfResourceStructure);
+        	
+        } catch (ArtifactInstallerException e) {
+        	
+        	sendDeployNotificationsForResource(vfResourceStructure,DistributionStatusEnum.DEPLOY_ERROR,e.getMessage());
+        	throw e;
+        }
+
+        if (vfResourceStructure.isDeployedSuccessfully()) {
+	        LOGGER.info (MessageEnum.ASDC_ARTIFACT_DEPLOY_SUC,
+	           		vfResourceStructure.getResourceInstance().getResourceName(),
+	          		vfResourceStructure.getResourceInstance().getResourceUUID(),
+	                String.valueOf (vfResourceStructure.getVfModuleStructure().size()), "ASDC", "deployResourceStructure");
+	        sendDeployNotificationsForResource(vfResourceStructure,DistributionStatusEnum.DEPLOY_OK ,null);
+        }
+
+    }
+
+    private enum NotificationType {
+    	DOWNLOAD, DEPLOY
+    }
+
+    private void sendASDCNotification (NotificationType notificationType,
+                                       String artifactURL,
+                                       String consumerID,
+                                       String distributionID,
+                                       DistributionStatusEnum status,
+                                       String errorReason,
+                                       long timestamp) {
+    	
+        String event = "Sending " + notificationType.name ()
+                       + "("
+                       + status.name ()
+                       + ")"
+                       + " notification to ASDC for artifact:"
+                       + artifactURL;
+        
+        if (errorReason != null) {
+        	event=event+"("+errorReason+")";
+        }
+        LOGGER.info (MessageEnum.ASDC_SEND_NOTIF_ASDC, notificationType.name (), status.name (), artifactURL, "ASDC", "sendASDCNotification");
+        LOGGER.debug (event);
+
+        long subStarttime = System.currentTimeMillis ();
+        String action = "";
+        try {
+            IDistributionStatusMessage message = new DistributionStatusMessage (artifactURL,
+                                                                                consumerID,
+                                                                                distributionID,
+                                                                                status,
+                                                                                timestamp);
+
+            switch (notificationType) {
+                case DOWNLOAD:
+                    if (errorReason != null) {
+                        this.distributionClient.sendDownloadStatus (message, errorReason);
+                    } else {
+                        this.distributionClient.sendDownloadStatus (message);
+                    }
+                    action = "sendDownloadStatus";
+                    break;
+                case DEPLOY:
+                    if (errorReason != null) {
+                        this.distributionClient.sendDeploymentStatus (message, errorReason);
+                    } else {
+                        this.distributionClient.sendDeploymentStatus (message);
+                    }
+                    action = "sendDeploymentdStatus";
+                    break;
+                default:
+                	break;
+            }
+        } catch (RuntimeException e) {
+            // TODO: May be a list containing the unsent notification should be
+            // kept
+            LOGGER.warn (MessageEnum.ASDC_SEND_NOTIF_ASDC_EXEC, "ASDC", "sendASDCNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException - sendASDCNotification", e);
+        }
+        LOGGER.recordMetricEvent (subStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully sent notification to ASDC", "ASDC", action, null);
+    }
+
+    public void treatNotification (INotificationData iNotif) {
+    	
+    	int noOfArtifacts = 0;
+    	for (IResourceInstance resource : iNotif.getResources ()) {
+    		noOfArtifacts += resource.getArtifacts ().size ();
+    	}
+        LOGGER.info (MessageEnum.ASDC_RECEIVE_CALLBACK_NOTIF,
+                     String.valueOf (noOfArtifacts),
+                     iNotif.getServiceUUID (), "ASDC", "treatNotification");
+        
+        try {
+        	LOGGER.debug(ASDCNotificationLogging.dumpASDCNotification(iNotif));
+			LOGGER.info(MessageEnum.ASDC_RECEIVE_SERVICE_NOTIF, iNotif.getServiceUUID(), "ASDC", "treatNotification");
+			this.changeControllerStatus(ASDCControllerStatus.BUSY);
+			// Process only the Resource artifacts in MSO
+			for (IResourceInstance resource : iNotif.getResources()) {
+
+				// We process only VNF resource on MSO Side
+				if ("VF".equals(resource.getResourceType())) {
+					this.processResourceNotification(iNotif,resource);		
+				}
+			}
+					
+					
+				
+        } catch (RuntimeException e) {
+            LOGGER.error (MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
+                          "Unexpected exception caught during the notification processing", "ASDC", "treatNotification", MsoLogger.ErrorCode.SchemaError, "RuntimeException in treatNotification",
+                          e);
+        } finally {
+            this.changeControllerStatus (ASDCControllerStatus.IDLE);
+        }
+    }
+
+        
+    private void processResourceNotification (INotificationData iNotif,IResourceInstance resource) {
+		// For each artifact, create a structure describing the VFModule in a ordered flat level
+		VfResourceStructure vfResourceStructure = new VfResourceStructure(iNotif,resource);
+		try {
+			
+			if (!this.checkResourceAlreadyDeployed(vfResourceStructure)) {
+				for (IArtifactInfo artifact : resource.getArtifacts()) {
+					
+						IDistributionClientDownloadResult resultArtifact = this.downloadTheArtifact(artifact, 
+								iNotif.getDistributionID());
+
+						if (resultArtifact != null) {
+							if (ASDCConfiguration.VF_MODULES_METADATA.equals(artifact.getArtifactType())) {
+								LOGGER.debug("VF_MODULE_ARTIFACT: "+new String(resultArtifact.getArtifactPayload(),"UTF-8"));
+								LOGGER.debug(ASDCNotificationLogging.dumpVfModuleMetaDataList(distributionClient.decodeVfModuleArtifact(resultArtifact.getArtifactPayload())));
+							}
+							vfResourceStructure.addArtifactToStructure(distributionClient,artifact, resultArtifact);
+				
+						} 
+
+				}
+				
+				this.deployResourceStructure(vfResourceStructure);
+				
+			} 
+		} catch (ArtifactInstallerException | ASDCDownloadException | UnsupportedEncodingException e) {
+			LOGGER.error(MessageEnum.ASDC_GENERAL_EXCEPTION_ARG,
+					"Exception caught during Installation of artifact", "ASDC", "processResourceNotification", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in processResourceNotification", e);
+		}
+    }
+    
+    private static final String UNKNOWN="Unknown";
+    
+    /**
+     * @return the address of the ASDC we are connected to.
+     */
+    public String getAddress () {
+        if (asdcConfig != null) {
+            return asdcConfig.getAsdcAddress ();
+        }
+        return UNKNOWN;
+    }
+
+    /**
+     * @return the environment name of the ASDC we are connected to.
+     */
+    public String getEnvironment () {
+        if (asdcConfig != null) {
+            return asdcConfig.getEnvironmentName ();
+        }
+        return UNKNOWN;
+    }
+
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCControllerStatus.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCControllerStatus.java
new file mode 100644
index 0000000..53de5fc
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCControllerStatus.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client;
+
+
+
+public enum ASDCControllerStatus {
+                                  STOPPED, IDLE, BUSY
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCGlobalController.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCGlobalController.java
new file mode 100644
index 0000000..4e10953
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/ASDCGlobalController.java
@@ -0,0 +1,217 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client;
+
+
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.openecomp.mso.asdc.client.exceptions.ASDCControllerException;
+import org.openecomp.mso.asdc.client.exceptions.ASDCParametersException;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.properties.MsoJsonProperties;
+import org.openecomp.mso.properties.MsoPropertiesException;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+
+
+
+public class ASDCGlobalController {
+
+    private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.ASDC);
+    private Map <String,ASDCController> controllers = new HashMap <String,ASDCController> ();
+        
+    private MsoJsonProperties msoProp= null;
+    
+    private void loadControllers () throws ASDCParametersException {
+    	
+		List<String> controllerNames = ASDCConfiguration.getAllDefinedControllers();
+
+		StringBuffer controllerListLog = new StringBuffer("List of controllers loaded:");
+		for (String controllerName : controllerNames) {
+			controllers.put(controllerName, new ASDCController(controllerName));
+			controllerListLog.append(controllerName);
+			controllerListLog.append(";");
+		}
+		LOGGER.debug(controllerListLog.toString());
+    }
+    
+    private boolean sameControllersDefined() throws ASDCParametersException {
+    	List<String> controllerNames = ASDCConfiguration.getAllDefinedControllers();
+    	if (controllerNames.size() == controllers.size()) {
+    		boolean areIdentical = true;
+    		
+    		for (String name:controllerNames) {
+    			if (!controllers.containsKey(name)) {
+    				areIdentical = false;
+    				break;
+    			}
+    		}
+    		return areIdentical;
+    		
+    	} else {
+    		return false;
+    	}
+    }
+    
+    /**
+     * Check that controllers list needs to be updated or not.
+     * @param return true if the list has been updated
+     */
+    private boolean updateControllersListIfNeeded ()  {
+    	boolean updateNeeded=false;
+    	try {
+    	
+			MsoPropertiesFactory msoPropFactory = new MsoPropertiesFactory();
+			MsoJsonProperties newMsoProp;
+	
+			newMsoProp = msoPropFactory.getMsoJsonProperties(ASDCConfiguration.MSO_PROP_ASDC);
+	
+			if (msoPropFactory.propertiesHaveChanged(ASDCConfiguration.MSO_PROP_ASDC, msoProp) && !sameControllersDefined()) {
+				updateNeeded = true;
+				LOGGER.debug("List of ASDC controllers has been changed, trying to kill them");
+				this.closeASDC();
+				
+				// Wait that all controllers are down before restarting, next pass will kill them all
+				if (this.controllers.size() == 0) {
+					msoProp = newMsoProp;
+					this.loadControllers();
+				}
+			} 			
+		
+    	} catch (ASDCParametersException e) {
+			 LOGGER.warn (MessageEnum.ASDC_LOAD_ASDC_CLIENT_EXC,
+                     "All ASDC Hosts",
+                     "All ASDC Envs", "ASDC", "", MsoLogger.ErrorCode.BusinessProcesssError, "ASDCParametersException in updateControllersListIfNeeded",
+                     e);
+		} catch (MsoPropertiesException e) {
+			 LOGGER.warn (MessageEnum.ASDC_LOAD_ASDC_CLIENT_EXC,
+                    "All ASDC Hosts",
+                    "All ASDC Envs", "ASDC", "", MsoLogger.ErrorCode.BusinessProcesssError, "MsoPropertiesException in updateControllersListIfNeeded",
+                    e);
+		}
+    	return updateNeeded;
+		
+
+    }
+    
+    /**
+     * Checks for each controller if it is STOPPED and restart if it is the case.
+     */
+    public void checkInStoppedState () {
+
+        for (ASDCController controller : controllers.values()) {
+            if (ASDCControllerStatus.STOPPED.equals (controller.getControllerStatus ())) {
+
+                // Try to restart just in case of issues
+                try {
+                    controller.initASDC ();
+                } catch (ASDCControllerException ec) {
+                    LOGGER.warn (MessageEnum.ASDC_INIT_ASDC_CLIENT_EXC,
+                                 controller.getAddress (),
+                                 controller.getEnvironment (), "ASDC", "", MsoLogger.ErrorCode.BusinessProcesssError, "ASDCControllerException in checkInStoppedState",
+                                 ec);
+                } catch (ASDCParametersException ep) {
+                    LOGGER.warn (MessageEnum.ASDC_LOAD_ASDC_CLIENT_EXC,
+                                 controller.getAddress (),
+                                 controller.getEnvironment (), "ASDC", "", MsoLogger.ErrorCode.BusinessProcesssError, "ASDCParametersException in checkInStoppedState",
+                                 ep);
+                } catch (RuntimeException | IOException e) {
+                    LOGGER.error (MessageEnum.ASDC_SINGLETON_CHECKT_EXC,
+                                  controller.getAddress (),
+                                  controller.getEnvironment (), "ASDC", "", MsoLogger.ErrorCode.BusinessProcesssError, "RuntimeException in checkInStoppedState",
+                                  e);
+                }
+            }
+        }
+    }
+
+    public void closeASDC () {
+    	List<String> controllerToRemove = new LinkedList<String>();
+    	
+        for (ASDCController controller : controllers.values()) {
+            try {
+                controller.closeASDC ();
+                controllerToRemove.add(controller.controllerName);
+                
+            } catch (RuntimeException e) {
+                LOGGER.warn (MessageEnum.ASDC_SHUTDOWN_ASDC_CLIENT_EXC,
+                             "RuntimeException",
+                             controller.getAddress (),
+                             controller.getEnvironment (), "ASDC", "closeASDC", MsoLogger.ErrorCode.BusinessProcesssError, "RuntimeException in closeASDC",
+                             e);
+            } catch (ASDCControllerException e) {
+                LOGGER.warn (MessageEnum.ASDC_SHUTDOWN_ASDC_CLIENT_EXC,
+                             "ASDCControllerException",
+                             controller.getAddress (),
+                             controller.getEnvironment (), "ASDC", "closeASDC", MsoLogger.ErrorCode.BusinessProcesssError, "ASDCControllerException in closeASDC",
+                             e);
+            }
+        }
+        
+        // Now remove the ones properly closed
+        for (String toRemove:controllerToRemove) {
+        	controllers.remove(toRemove);
+        }
+        
+    }
+
+    /**
+     * Check whether the config has been changed
+     */
+    public boolean updateControllersConfigIfNeeded () {
+    	boolean listUpdated=updateControllersListIfNeeded();
+    	if (!listUpdated) {
+    	
+	        for (ASDCController controller : controllers.values()) {
+	            try {
+	                controller.updateConfigIfNeeded ();
+	            } catch (ASDCControllerException ec) {
+	                LOGGER.warn (MessageEnum.ASDC_INIT_ASDC_CLIENT_EXC,
+	                             controller.getAddress (),
+	                             controller.getEnvironment (), "ASDC", "closeASDC", MsoLogger.ErrorCode.BusinessProcesssError, "ASDCControllerException in updateControllersConfigIfNeeded",
+	                             ec);
+	            } catch (ASDCParametersException ep) {
+	                LOGGER.warn (MessageEnum.ASDC_LOAD_ASDC_CLIENT_EXC,
+	                             controller.getAddress (),
+	                             controller.getEnvironment (), "ASDC", "closeASDC", MsoLogger.ErrorCode.BusinessProcesssError, "ASDCParametersException in updateControllersConfigIfNeeded",
+	                             ep);
+	            } catch (RuntimeException | IOException e) {
+	                LOGGER.error (MessageEnum.ASDC_SINGLETON_CHECKT_EXC,
+	                              controller.getAddress (),
+	                              controller.getEnvironment (), "ASDC", "closeASDC", MsoLogger.ErrorCode.BusinessProcesssError, "RuntimeException in updateControllersConfigIfNeeded",
+	                              e);
+	            }
+	        }
+    	}
+    	return listUpdated;
+    }
+
+	public Map<String, ASDCController> getControllers() {
+		return controllers;
+	}
+    
+    
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/DistributionStatusMessage.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/DistributionStatusMessage.java
new file mode 100644
index 0000000..dddcaff
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/DistributionStatusMessage.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client;
+
+
+import org.openecomp.sdc.api.consumer.IDistributionStatusMessage;
+import org.openecomp.sdc.utils.DistributionStatusEnum;
+
+public class DistributionStatusMessage implements IDistributionStatusMessage {
+
+	private String artifactURL;
+	
+	private String consumerID;
+	
+	private String distributionID;
+	
+	private DistributionStatusEnum distributionStatus;
+	
+	private long timestamp;
+	
+	public DistributionStatusMessage (final String artifactUrl, final String consumerId,final String distributionId, final DistributionStatusEnum distributionStatusEnum, final long timestampL) {
+		artifactURL = artifactUrl;
+		consumerID = consumerId;
+		distributionID = distributionId;
+		distributionStatus = distributionStatusEnum;
+		timestamp = timestampL;
+	}
+	
+	@Override
+	public String getArtifactURL() {
+		
+		return artifactURL;
+	}
+
+	@Override
+	public String getConsumerID() {
+	
+		return consumerID;
+	}
+
+	@Override
+	public String getDistributionID() {
+		
+		return distributionID;
+	}
+
+	@Override
+	public DistributionStatusEnum getStatus() {
+	
+		return distributionStatus;
+	}
+
+	@Override
+	public long getTimestamp() {
+		
+		return timestamp;
+	}
+
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCControllerException.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCControllerException.java
new file mode 100644
index 0000000..72c5a5a
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCControllerException.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client.exceptions;
+
+
+/**
+ * Exception of the ASDC controller.
+ */
+public class ASDCControllerException extends Exception {
+
+	/**
+     * serialization id.
+	 */
+	private static final long serialVersionUID = -4236006447255525130L;
+
+	/**
+     * @param message The message to dump
+     * @param cause The Throwable cause object
+     */
+    public ASDCControllerException (final String message) {
+        super (message);
+       
+    }
+	
+    /**
+     * @param message The message to dump
+     * @param cause The Throwable cause object
+     */
+    public ASDCControllerException (final String message, final Throwable cause) {
+        super (message, cause);
+       
+    }
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCDownloadException.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCDownloadException.java
new file mode 100644
index 0000000..59d3223
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCDownloadException.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client.exceptions;
+
+
+/**
+ * Exception during download from ASDC.
+ */
+public class ASDCDownloadException extends Exception {
+
+	/**
+     * serialization id.
+	 */
+	private static final long serialVersionUID = -5276848693231134901L;
+
+	/**
+     * @param message The message to dump
+     * @param cause The Throwable cause object
+     */
+    public ASDCDownloadException (final String message) {
+        super (message);
+       
+    }
+	
+    /**
+     * @param message The message to dump
+     * @param cause The Throwable cause object
+     */
+    public ASDCDownloadException (final String message, final Throwable cause) {
+        super (message, cause);
+       
+    }
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCParametersException.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCParametersException.java
new file mode 100644
index 0000000..fdedd40
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ASDCParametersException.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client.exceptions;
+
+
+/**
+ * Exception of the ASDC controller.
+ */
+public class ASDCParametersException extends Exception {
+
+	/**
+     * serialization id.
+	 */
+	private static final long serialVersionUID = 8425657297510362736L;
+
+    /**
+     * @param message The message to dump
+     * @param cause The Throwable cause object
+     */
+    public ASDCParametersException (final String message) {
+        super (message);
+       
+    }
+	
+    /**
+     * @param message The message to dump
+     * @param cause The Throwable cause object
+     */
+    public ASDCParametersException (final String message, final Throwable cause) {
+        super (message, cause);
+       
+    }
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ArtifactInstallerException.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ArtifactInstallerException.java
new file mode 100644
index 0000000..af698ad
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/client/exceptions/ArtifactInstallerException.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.client.exceptions;
+
+
+/**
+ * Exception during artifact installation.
+ */
+public class ArtifactInstallerException extends Exception {
+
+	/**
+     * serialization id.
+	 */
+	private static final long serialVersionUID = 4095937499475915021L;
+
+    /**
+     * @param message The message to dump
+     * @param cause The Throwable cause object
+     */
+    public ArtifactInstallerException (final String message) {
+        super (message);
+       
+    }
+	
+    /**
+     * @param message The message to dump
+     * @param cause The Throwable cause object
+     */
+    public ArtifactInstallerException (final String message, final Throwable cause) {
+        super (message, cause);
+       
+    }
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/healthcheck/HealthCheckHandler.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/healthcheck/HealthCheckHandler.java
new file mode 100644
index 0000000..f0b6ec4
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/healthcheck/HealthCheckHandler.java
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.healthcheck;
+
+
+import org.openecomp.mso.MsoStatusUtil;
+import org.openecomp.mso.db.catalog.CatalogDatabase;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.properties.MsoJsonProperties;
+import org.openecomp.mso.properties.MsoPropertiesFactory;
+import org.openecomp.mso.HealthCheckUtils;
+import org.openecomp.mso.utils.UUIDChecker;
+import org.apache.http.HttpStatus;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+
+
+@Path("/")
+	public class HealthCheckHandler {
+		
+		private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.ASDC);
+		private static final String MSO_PROP_ASDC = "MSO_PROP_ASDC";
+		private static MsoPropertiesFactory msoPropertiesFactory = new MsoPropertiesFactory();
+
+		private static final String SUC_HTML = "<!DOCTYPE html><html><head><meta charset=\"ISO-8859-1\"><title>Health Check</title></head><body>Application ready</body></html>";
+		private static final String NOT_FOUND = "<!DOCTYPE html><html><head><meta charset=\"ISO-8859-1\"><title>Application Not Ready</title></head><body>Application Not Ready. Properties file missing or invalid or database Connection failed</body></html>";
+
+		private static final Response OK_RESPONSE = Response.status (HttpStatus.SC_OK).entity (SUC_HTML).build ();
+		private static final Response NOK_RESPONSE = Response.status (HttpStatus.SC_SERVICE_UNAVAILABLE).entity (NOT_FOUND).build ();
+
+		@HEAD
+	    @GET
+	    @Path("/healthcheck")
+	    @Produces("text/html")
+	    public Response healthcheck (@QueryParam("requestId") String requestId) {
+			long startTime = System.currentTimeMillis ();
+			MsoLogger.setServiceName ("Healthcheck");
+			UUIDChecker.verifyOldUUID(requestId, msoLogger);
+			HealthCheckUtils healthCheck = new HealthCheckUtils ();
+			if (!healthCheck.siteStatusCheck(msoLogger, startTime)) {
+				return HealthCheckUtils.HEALTH_CHECK_NOK_RESPONSE;
+			}
+
+			MsoJsonProperties props = loadMsoProperties ();
+			if (props == null) {
+				msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.ServiceNotAvailable, "Application Not Ready");
+				return HealthCheckUtils.NOT_STARTED_RESPONSE;
+			}
+
+			if (!healthCheck.catalogDBCheck (msoLogger, startTime)) {
+				return HealthCheckUtils.NOT_STARTED_RESPONSE;
+			}
+			msoLogger.debug("healthcheck - Successful");
+			return HealthCheckUtils.HEALTH_CHECK_RESPONSE;
+	    }
+
+		private MsoJsonProperties loadMsoProperties () {
+			MsoJsonProperties msoProperties;
+			try {
+				msoProperties = msoPropertiesFactory.getMsoJsonProperties(MSO_PROP_ASDC);
+			} catch (Exception e) {
+				msoLogger.error (MessageEnum.ASDC_PROPERTIES_NOT_FOUND, MSO_PROP_ASDC, "", "", MsoLogger.ErrorCode.DataError, "Exception - getMsoJsonProperties", e);
+				return null;
+			}
+
+			if (msoProperties !=null && msoProperties.getJsonRootNode().getElements().hasNext()) {
+				return msoProperties;
+			} else {
+				msoLogger.error (MessageEnum.ASDC_PROPERTIES_NOT_FOUND , MSO_PROP_ASDC, "", "", MsoLogger.ErrorCode.DataError, "ASDC properties not found");
+				return  null;
+			}
+		}
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/ASDCElementInfo.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/ASDCElementInfo.java
new file mode 100644
index 0000000..5e59be5
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/ASDCElementInfo.java
@@ -0,0 +1,212 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.installer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.sdc.api.notification.IResourceInstance;
+import org.openecomp.sdc.api.notification.IVfModuleMetadata;
+import org.openecomp.mso.asdc.client.ASDCConfiguration;
+
+/**
+ * A class representing a generic element whose information can be used for example to log artifacts, resource... data.
+ */
+public class ASDCElementInfo {
+	
+	/**
+	 * A default, empty instance used in case a source element was not correctly provided.
+	 */
+	public static final ASDCElementInfo EMPTY_INSTANCE = new ASDCElementInfo();
+	
+	/**
+	 * Used to define the other possible ASDC Element types (usually in addition to existing artifact types, etc.).<br/>
+	 * <br/>
+	 * Possible types allowed:<br/>
+	 * <ul>
+	 * <li>{@link ASDCElementTypeEnum#VNF_RESOURCE}</li>
+	 * <ul>
+	 */
+	public static enum ASDCElementTypeEnum {
+		/**
+		 * The type VNF_RESOURCE. Represents a VNF_RESOURCE element.
+		 */
+		VNF_RESOURCE
+	};
+
+	/**
+	 * The map of element information fields useful for logging. The complete contents of this list will be concatenated.
+	 */
+	private final Map<String, String> elementInfoMap = new HashMap<>();
+	
+	/**
+	 * The type of this element.
+	 */
+	private final String type;
+	
+	private ASDCElementInfo () {
+		// Private parameterless constructor. Not visible, only used for EMPTY_INSTANCE.
+		this.type = "";
+	}
+	
+	/**
+	 * Artifact-type based constructor. Requires a valid artifact type.
+	 * @param artifactType The artifact type
+	 */
+	private ASDCElementInfo (String artifactType) {
+		// We need the exact type name here...
+		this.type = artifactType;
+	}
+	
+	/**
+	 * 'Other element type'-based constructor. Requires a valid element type.
+	 * @param elementType An ASDCElementTypeEnum entry. This will usually contain enumerated types not in the existing
+	 */
+	private ASDCElementInfo (ASDCElementTypeEnum elementType) {
+		// We need the exact type name here...
+		this.type = elementType.name();
+	}
+	
+	/**
+	 * Add an information entry (name, UUID, etc.) from an artifact/resource/..., once a at time.
+	 * 
+	 * @param key The key (name) of the information entry (Artifact UUID, Resource Name, etc.)
+	 * @param value The value bound to the information entry.
+	 */
+	public final void addElementInfo(String key, String value) {
+		if ((key != null) && (value != null)) {
+			this.getElementInfoMap().put(key, value);
+		}
+	}
+	
+	/**
+	 * Returns an aggregated, formatted list of the expected details about an ASDC element.
+	 * (non-Javadoc)
+	 * @return An aggregated list of element information entries, comma-separated.
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public final String toString() {
+		StringBuffer sb = new StringBuffer();
+		List<String> aggregatedElements = new ArrayList<>();
+		for (Entry<String, String> entry : this.getElementInfoMap().entrySet()) {
+			aggregatedElements.add(entry.getKey() + ": " + entry.getValue());
+		}
+		sb.append(aggregatedElements.size() > 0 ? aggregatedElements.get(0) : "");
+		if (aggregatedElements.size() > 1) {
+			for (int i = 1; i < aggregatedElements.size(); ++i) {
+				sb.append (", ");
+				sb.append(aggregatedElements.get(i));
+			}
+		}
+		return sb.toString();
+	}
+	
+	/**
+	 * The type that was defined at creation time. This is typically VNF_RESOURCE, VF_MODULE_METADATA, HEAT_ENV, etc.
+	 * @return The type of this element information type. This will usually be either an ArtifactTypeEnum entry name or an ASDCElementTypeEnum entry name.
+	 * @see ASDCElementInfo.ASDCElementTypeEnum
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Provides the map of all element information entries for this type.
+	 * @return A map of all element information entries which will be used by the toString() method.
+	 * @see ASDCElementInfo#toString()
+	 */
+	protected Map<String, String> getElementInfoMap() {
+		return elementInfoMap;
+	}
+
+	/**
+	 * Create an ASDCElementInfo object from a VNF Resource.<br/>
+	 * <br/>
+	 * <b>Used information:</b><br/>
+	 * <ul>
+	 * <li>Resource Instance Name</li>
+	 * <li>Resource Instance UUID</li>
+	 * </ul>
+	 * 
+	 * @param vfResourceStructure The VfResourceStructure to use as source of information (see {@link VfResourceStructure}).
+	 * @return an ASDCElementInfo using the information held in the VNF Resource.
+	 */
+	public static final ASDCElementInfo createElementFromVfResourceStructure (VfResourceStructure vfResourceStructure) {
+		if (vfResourceStructure == null) {
+			return EMPTY_INSTANCE;
+		}
+		ASDCElementInfo elementInfo = new ASDCElementInfo(ASDCElementTypeEnum.VNF_RESOURCE);
+		IResourceInstance resourceInstance = vfResourceStructure.getResourceInstance();
+		elementInfo.addElementInfo("Resource Instance Name", resourceInstance.getResourceInstanceName());
+		elementInfo.addElementInfo("Resource Instance Invariant UUID", resourceInstance.getResourceInvariantUUID());
+		return elementInfo;
+	}
+
+	/**
+	 * Create an ASDCElementInfo object from a VF Module.<br/>
+	 * <br/>
+	 * <b>Used information:</b><br/>
+	 * <ul>
+	 * <li>Module Model Name</li>
+	 * <li>Module Model UUID</li>
+	 * </ul>
+	 * 
+	 * @param vfModuleStructure The VfModuleStructure to use as source of information (see {@link VfModuleStructure}).
+	 * @return an ASDCElementInfo using the information held in the VF Module.
+	 */
+	public static final ASDCElementInfo createElementFromVfModuleStructure (VfModuleStructure vfModuleStructure) {
+		if (vfModuleStructure == null) {
+			return EMPTY_INSTANCE;
+		}
+		ASDCElementInfo elementInfo = new ASDCElementInfo(ASDCConfiguration.VF_MODULES_METADATA);
+		IVfModuleMetadata moduleMetadata = vfModuleStructure.getVfModuleMetadata();
+		elementInfo.addElementInfo("Module Model Name", moduleMetadata.getVfModuleModelName());
+		elementInfo.addElementInfo("Module Model Invariant UUID", moduleMetadata.getVfModuleModelInvariantUUID());
+		return elementInfo;
+	}
+	
+	/**
+	 * Create an ASDCElementInfo object from an IArtfiactInfo instance.<br/>
+	 * <br/>
+	 * <b>Used information:</b><br/>
+	 * <ul>
+	 * <li>IArtifactInfo Name</li>
+	 * <li>IArtifactInfo UUID</li>
+	 * </ul>
+	 * 
+	 * @param artifactInfo The VfModuleStructure to use as source of information (see {@link IArtifactInfo}).
+	 * @return an ASDCElementInfo using the information held in the IArtifactInfo instance.
+	 */
+	public static final ASDCElementInfo createElementFromVfArtifactInfo (IArtifactInfo artifactInfo) {
+		if (artifactInfo == null) {
+			return EMPTY_INSTANCE;
+		}
+		ASDCElementInfo elementInfo = new ASDCElementInfo(artifactInfo.getArtifactType());
+		elementInfo.addElementInfo(elementInfo.getType() + " Name", artifactInfo.getArtifactName());
+		elementInfo.addElementInfo(elementInfo.getType() + " UUID", artifactInfo.getArtifactUUID());
+		return elementInfo;
+	}
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/BigDecimalVersion.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/BigDecimalVersion.java
new file mode 100644
index 0000000..a0932ed
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/BigDecimalVersion.java
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.installer;
+
+
+import java.math.BigDecimal;
+
+public class BigDecimalVersion {
+	  
+	/**
+     * This method truncates and convert the version String provided in the notification.
+     * 
+     * @param version The version to check
+     * @return A BigDecimal value checked and truncated
+     */
+    public static BigDecimal castAndCheckNotificationVersion(String version) {
+    	// Truncate the version if bad type
+    	String[] splitVersion = version.split("\\.");
+    	StringBuffer newVersion = new StringBuffer();
+    	if (splitVersion.length > 1) {
+	    	newVersion.append(splitVersion[0]);
+	    	newVersion.append(".");
+	    	newVersion.append(splitVersion[1]);
+    	} else {
+    		return new BigDecimal(splitVersion[0]);
+    	}
+    	
+    	for (int i=2;i<splitVersion.length;i++) {
+    		newVersion.append(splitVersion[i]);
+    	}
+    	
+    	return new BigDecimal(newVersion.toString());
+    }
+    
+    /**
+     * This method truncates and convert the version String provided in the notification.
+     * 
+     * @param version The version to check
+     * @return A String value checked and truncated to Decimal format
+     */
+    public static String castAndCheckNotificationVersionToString (String version) {
+    	return castAndCheckNotificationVersion(version).toString();
+    }
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/IArtifactOrchestrator.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/IArtifactOrchestrator.java
new file mode 100644
index 0000000..25c3b9c
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/IArtifactOrchestrator.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.installer;
+
+
+
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.sdc.api.notification.INotificationData;
+import org.openecomp.sdc.api.notification.IResourceInstance;
+import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
+import org.openecomp.mso.asdc.client.exceptions.ArtifactInstallerException;
+
+public interface IArtifactOrchestrator {
+
+	void installTheArtifact (INotificationData iNotif, IResourceInstance resource, IArtifactInfo artifact, IDistributionClientDownloadResult downloadResult) throws ArtifactInstallerException;
+
+	boolean isArtifactAlreadyDeployed (INotificationData iNotif,IResourceInstance resource,IArtifactInfo artifact) throws ArtifactInstallerException;
+
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/IVfResourceInstaller.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/IVfResourceInstaller.java
new file mode 100644
index 0000000..5f0f930
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/IVfResourceInstaller.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.installer;
+
+
+
+import org.openecomp.mso.asdc.client.exceptions.ArtifactInstallerException;
+
+public interface IVfResourceInstaller {
+
+	boolean isResourceAlreadyDeployed (VfResourceStructure vfResourceStructure) throws ArtifactInstallerException;
+
+	public void installTheResource (VfResourceStructure vfResourceStructure) throws ArtifactInstallerException;
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfModuleArtifact.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfModuleArtifact.java
new file mode 100644
index 0000000..c7f19ea
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfModuleArtifact.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.installer;
+
+
+import java.io.UnsupportedEncodingException;
+
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
+
+/**
+ * The structure that contains the artifactInfo and its associated DownloadedResult. 
+ *
+ */
+public final class VfModuleArtifact {
+	private final IArtifactInfo artifactInfo;
+	private int deployedInDb=0;
+	private final String result;
+		
+	private Object catalogObject;	
+		
+	public VfModuleArtifact(IArtifactInfo artifactinfo,IDistributionClientDownloadResult clientResult) throws UnsupportedEncodingException {
+		artifactInfo=artifactinfo;
+		result = new String(clientResult.getArtifactPayload(), "UTF-8");
+		
+	}
+
+	public Object getCatalogObject() {
+		return catalogObject;
+	}
+
+	public void setCatalogObject(Object catalogObject) {
+		this.catalogObject = catalogObject;
+	}
+
+	public IArtifactInfo getArtifactInfo() {
+		return artifactInfo;
+	}
+
+	public String getResult() {
+		return result;
+	}
+
+	public int getDeployedInDb() {
+		return deployedInDb;
+	}
+
+	public void incrementDeployedInDB() {
+		++deployedInDb;
+	}
+	
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfModuleStructure.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfModuleStructure.java
new file mode 100644
index 0000000..239bc8a
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfModuleStructure.java
@@ -0,0 +1,117 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.installer;
+
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.openecomp.sdc.api.notification.IVfModuleMetadata;
+import org.openecomp.mso.asdc.client.ASDCConfiguration;
+import org.openecomp.mso.asdc.client.exceptions.ArtifactInstallerException;
+import org.openecomp.mso.db.catalog.beans.VfModule;
+
+public final class VfModuleStructure {
+	
+	private final IVfModuleMetadata vfModuleMetadata;
+	
+	private final VfResourceStructure parentVfResource;
+	
+	private VfModule catalogVfModule;
+	/**
+	 * The list of artifact existing in this resource hashed by artifactType.
+	 */
+	private final Map<String, List<VfModuleArtifact>> artifactsMap;
+	
+	public VfModuleStructure(VfResourceStructure vfParentResource,IVfModuleMetadata vfmoduleMetadata) throws ArtifactInstallerException {
+		
+		vfModuleMetadata = vfmoduleMetadata;
+		parentVfResource = vfParentResource;
+		
+		artifactsMap = new HashMap<String, List<VfModuleArtifact>>();
+				
+		for (String artifactUUID:this.vfModuleMetadata.getArtifacts()) {
+			if (vfParentResource.getArtifactsMapByUUID().containsKey(artifactUUID)) {
+				this.addToStructure(vfParentResource.getArtifactsMapByUUID().get(artifactUUID));
+			} else {
+				throw new ArtifactInstallerException("Artifact (UUID:"+artifactUUID+ ") referenced in the VFModule UUID list has not been downloaded, cancelling the Resource deployment");
+			}
+		}
+	}
+	
+	private void addToStructure(VfModuleArtifact vfModuleArtifact) {
+		
+		if (artifactsMap.containsKey(vfModuleArtifact.getArtifactInfo().getArtifactType())) {
+			artifactsMap.get(vfModuleArtifact.getArtifactInfo().getArtifactType()).add(vfModuleArtifact);
+			
+		} else {
+			List<VfModuleArtifact> nestedList = new LinkedList<VfModuleArtifact>();
+			nestedList.add(vfModuleArtifact);
+			
+			artifactsMap.put(vfModuleArtifact.getArtifactInfo().getArtifactType(), nestedList);
+		}
+	}
+	
+	public List<VfModuleArtifact> getOrderedArtifactList() {
+		
+		List <VfModuleArtifact> artifactsList = new LinkedList <VfModuleArtifact>();
+		
+		artifactsList.addAll(artifactsMap.get(ASDCConfiguration.HEAT));
+		artifactsList.addAll(artifactsMap.get(ASDCConfiguration.HEAT_ENV));
+		artifactsList.addAll(artifactsMap.get(ASDCConfiguration.HEAT_VOL));
+		
+		for (VfModuleArtifact artifact:(artifactsMap.get(ASDCConfiguration.HEAT_NESTED))) {
+			artifactsList.add(artifact);
+		}
+		
+		for (VfModuleArtifact artifact:(artifactsMap.get(ASDCConfiguration.HEAT_ARTIFACT))) {
+			artifactsList.add(artifact);
+		}
+		
+		artifactsList.addAll(artifactsMap.get(ASDCConfiguration.HEAT_VOL));
+		
+		return null;
+	}
+
+	public IVfModuleMetadata getVfModuleMetadata() {
+		return vfModuleMetadata;
+	}
+
+	public VfResourceStructure getParentVfResource() {
+		return parentVfResource;
+	}
+
+	public Map<String, List<VfModuleArtifact>> getArtifactsMap() {
+		return artifactsMap;
+	}
+
+
+	public VfModule getCatalogVfModule() {
+		return catalogVfModule;
+	}
+
+	public void setCatalogVfModule(VfModule catalogVfModule) {
+		this.catalogVfModule = catalogVfModule;
+	}
+	
+	
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfResourceStructure.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfResourceStructure.java
new file mode 100644
index 0000000..7be5e70
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/VfResourceStructure.java
@@ -0,0 +1,165 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.installer;
+
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.openecomp.sdc.api.IDistributionClient;
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.sdc.api.notification.INotificationData;
+import org.openecomp.sdc.api.notification.IResourceInstance;
+import org.openecomp.sdc.api.notification.IVfModuleMetadata;
+import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;
+import org.openecomp.mso.asdc.client.ASDCConfiguration;
+import org.openecomp.mso.asdc.client.exceptions.ArtifactInstallerException;
+import org.openecomp.mso.db.catalog.beans.Service;
+import org.openecomp.mso.db.catalog.beans.VnfResource;
+
+/**
+ * This structure exists to avoid having issues if the order of the vfResource/vfmodule artifact is not good (tree structure).
+ * 
+ *
+ */
+public final class VfResourceStructure {
+	
+	private boolean isDeployedSuccessfully=false;
+	/**
+	 * The Raw notification data. 
+	 */
+	private final INotificationData notification;
+	
+	/**
+	 * The resource we will try to deploy.
+	 */
+	private final IResourceInstance resourceInstance;
+	
+	/**
+	 * The list of VfModules defined for this resource.
+	 */
+	private final List<VfModuleStructure> vfModulesStructureList;
+	
+	/**
+	 * The list of VfModulesMetadata defined for this resource.
+	 */
+	private List<IVfModuleMetadata> vfModulesMetadataList;
+	
+	private VnfResource catalogVnfResource;
+	
+	private Service catalogService;
+	
+	/**
+	 * The list of artifacts existing in this resource hashed by UUID.
+	 */
+	private final Map<String, VfModuleArtifact> artifactsMapByUUID; 
+	
+		
+	public VfResourceStructure(INotificationData notificationdata, IResourceInstance resourceinstance) {
+		notification=notificationdata;
+		resourceInstance=resourceinstance;
+		
+
+		vfModulesStructureList = new LinkedList<VfModuleStructure>();
+		artifactsMapByUUID =  new HashMap<String, VfModuleArtifact>();
+	}
+	
+	public void addArtifactToStructure(IDistributionClient distributionClient,IArtifactInfo artifactinfo,IDistributionClientDownloadResult clientResult) throws UnsupportedEncodingException {
+		VfModuleArtifact vfModuleArtifact = new VfModuleArtifact(artifactinfo,clientResult);
+		
+		switch(artifactinfo.getArtifactType()) {
+			case ASDCConfiguration.HEAT:
+			case ASDCConfiguration.HEAT_ENV:
+			case ASDCConfiguration.HEAT_VOL:
+			case ASDCConfiguration.HEAT_NESTED:    // For 1607 only 1 level tree is supported
+			case ASDCConfiguration.HEAT_ARTIFACT: 
+			case ASDCConfiguration.HEAT_NET:
+			case ASDCConfiguration.OTHER:
+				artifactsMapByUUID.put(artifactinfo.getArtifactUUID(), vfModuleArtifact);
+				break;
+
+			case ASDCConfiguration.VF_MODULES_METADATA:
+				vfModulesMetadataList = distributionClient.decodeVfModuleArtifact(clientResult.getArtifactPayload());
+				break;
+
+			default:
+				break;
+
+		}
+	}
+
+	public void createVfModuleStructures() throws ArtifactInstallerException {
+		
+		if (vfModulesMetadataList == null) {
+			throw new ArtifactInstallerException("VfModule Meta DATA could not be decoded properly or was not present in the notification");
+		}
+		for (IVfModuleMetadata vfModuleMeta:vfModulesMetadataList) {
+			vfModulesStructureList.add(new VfModuleStructure(this,vfModuleMeta));
+		}
+	}
+	
+	public INotificationData getNotification() {
+		return notification;
+	}
+
+	public IResourceInstance getResourceInstance() {
+		return resourceInstance;
+	}
+
+	public List<VfModuleStructure> getVfModuleStructure() {
+		return vfModulesStructureList;
+	}
+
+	public boolean isDeployedSuccessfully() {
+		return isDeployedSuccessfully;
+	}
+	
+	public void setSuccessfulDeployment() {
+		isDeployedSuccessfully = true;
+	}
+
+	public Map<String, VfModuleArtifact> getArtifactsMapByUUID() {
+		return artifactsMapByUUID;
+	}
+
+	public List<VfModuleStructure> getVfModulesStructureList() {
+		return vfModulesStructureList;
+	}
+
+	public VnfResource getCatalogVnfResource() {
+		return catalogVnfResource;
+	}
+
+	public void setCatalogVnfResource(VnfResource catalogVnfResource) {
+		this.catalogVnfResource = catalogVnfResource;
+	}
+
+	public Service getCatalogService() {
+		return catalogService;
+	}
+
+	public void setCatalogService(Service catalogService) {
+		this.catalogService = catalogService;
+	}
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/heat/VfResourceInstaller.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/heat/VfResourceInstaller.java
new file mode 100644
index 0000000..4cef0f1
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/installer/heat/VfResourceInstaller.java
@@ -0,0 +1,596 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.installer.heat;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.hibernate.exception.ConstraintViolationException;
+import org.hibernate.exception.LockAcquisitionException;
+
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.mso.asdc.client.ASDCConfiguration;
+import org.openecomp.mso.asdc.client.exceptions.ArtifactInstallerException;
+import org.openecomp.mso.asdc.installer.ASDCElementInfo;
+import org.openecomp.mso.asdc.installer.BigDecimalVersion;
+import org.openecomp.mso.asdc.installer.IVfResourceInstaller;
+import org.openecomp.mso.asdc.installer.VfModuleArtifact;
+import org.openecomp.mso.asdc.installer.VfModuleStructure;
+import org.openecomp.mso.asdc.installer.VfResourceStructure;
+import org.openecomp.mso.asdc.util.YamlEditor;
+import org.openecomp.mso.db.catalog.CatalogDatabase;
+import org.openecomp.mso.db.catalog.beans.HeatEnvironment;
+import org.openecomp.mso.db.catalog.beans.HeatFiles;
+import org.openecomp.mso.db.catalog.beans.HeatTemplate;
+import org.openecomp.mso.db.catalog.beans.HeatTemplateParam;
+import org.openecomp.mso.db.catalog.beans.Service;
+import org.openecomp.mso.db.catalog.beans.VfModule;
+import org.openecomp.mso.db.catalog.beans.VnfResource;
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+
+public class VfResourceInstaller implements IVfResourceInstaller {
+
+	private MsoLogger logger;
+
+	public VfResourceInstaller() {
+		logger = MsoLogger.getMsoLogger(MsoLogger.Catalog.ASDC);
+	}
+
+	@Override
+	public boolean isResourceAlreadyDeployed(VfResourceStructure vfResourceStructure)
+			throws ArtifactInstallerException {
+		boolean status = false;
+
+		try (CatalogDatabase db = new CatalogDatabase()) {
+
+			logger.info(MessageEnum.ASDC_CHECK_HEAT_TEMPLATE, "VNFResource",
+					VfResourceInstaller.createVNFName(vfResourceStructure),
+					BigDecimalVersion.castAndCheckNotificationVersionToString(
+							vfResourceStructure.getNotification().getServiceVersion()), "", "");
+
+			VnfResource vnfResource = db.getVnfResource(
+					VfResourceInstaller.createVNFName(vfResourceStructure),
+					BigDecimalVersion.castAndCheckNotificationVersionToString(
+							vfResourceStructure.getNotification().getServiceVersion()));
+
+			if (vnfResource != null) {
+				status = true;
+
+			}
+
+			if (status) {
+				logger.info(MessageEnum.ASDC_ARTIFACT_ALREADY_DEPLOYED_DETAIL,
+						vfResourceStructure.getResourceInstance().getResourceInstanceName(),
+						vfResourceStructure.getResourceInstance().getResourceUUID(),
+						vfResourceStructure.getNotification().getServiceName(),
+						BigDecimalVersion.castAndCheckNotificationVersionToString(
+								vfResourceStructure.getNotification().getServiceVersion()),
+						vfResourceStructure.getNotification().getServiceUUID(),
+						vfResourceStructure.getResourceInstance().getResourceName(), "", "");
+			} else {
+				logger.info(MessageEnum.ASDC_ARTIFACT_NOT_DEPLOYED_DETAIL,
+						vfResourceStructure.getResourceInstance().getResourceInstanceName(),
+						vfResourceStructure.getResourceInstance().getResourceUUID(),
+						vfResourceStructure.getNotification().getServiceName(),
+						BigDecimalVersion.castAndCheckNotificationVersionToString(
+								vfResourceStructure.getNotification().getServiceVersion()),
+						vfResourceStructure.getNotification().getServiceUUID(), 
+						vfResourceStructure.getResourceInstance().getResourceName(),"", "");
+			}
+
+			return status;
+
+		} catch (Exception e) {
+			logger.error(MessageEnum.ASDC_ARTIFACT_CHECK_EXC, "", "", MsoLogger.ErrorCode.SchemaError, "Exception - isResourceAlreadyDeployed");
+			throw new ArtifactInstallerException("Exception caught during checking existence of the VNF Resource.", e);
+		}
+	}
+
+	@Override
+	public void installTheResource(VfResourceStructure vfResourceStructure) throws ArtifactInstallerException {
+
+		// 1. Add the DB object list (Hashed) to be created from the HashMap
+		// UUID
+		// The DB objects will be stored in each VfModuleArtifact objects
+		// Those objects could be reused by different VfModule
+
+		for (VfModuleArtifact vfModuleArtifact : vfResourceStructure.getArtifactsMapByUUID().values()) {
+
+			switch (vfModuleArtifact.getArtifactInfo().getArtifactType()) {
+			case ASDCConfiguration.HEAT:
+			case ASDCConfiguration.HEAT_VOL:
+			case ASDCConfiguration.HEAT_NESTED:
+				VfResourceInstaller.createHeatTemplateFromArtifact(vfResourceStructure, vfModuleArtifact);
+				break;
+			case ASDCConfiguration.HEAT_ENV:
+				VfResourceInstaller.createHeatEnvFromArtifact(vfResourceStructure, vfModuleArtifact);
+				break;
+			case ASDCConfiguration.HEAT_ARTIFACT:
+				VfResourceInstaller.createHeatFileFromArtifact(vfResourceStructure, vfModuleArtifact);
+				break;
+			case ASDCConfiguration.HEAT_NET:
+			case ASDCConfiguration.OTHER:
+				logger.warn(MessageEnum.ASDC_ARTIFACT_TYPE_NOT_SUPPORT, vfModuleArtifact.getArtifactInfo().getArtifactType()+"(Artifact Name:"+vfModuleArtifact.getArtifactInfo().getArtifactName()+")", "", "", MsoLogger.ErrorCode.DataError, "Artifact type not supported");
+				break;
+			default:
+				break;
+
+			}
+		}
+		
+		// in case of deployment failure, use a string that will represent the type of artifact that failed...
+		List<ASDCElementInfo> artifactListForLogging = new ArrayList<>();
+		
+		CatalogDatabase catalogDB = new CatalogDatabase();
+		// 2. Create the VFModules/VNFResource objects by linking them to the
+		// objects created before and store them in Resource/module structure
+		// Opening a DB transaction, starting from here
+		try {
+			
+			VfResourceInstaller.createService(vfResourceStructure);
+			
+			VfResourceInstaller.createVnfResource(vfResourceStructure);
+
+			// Add this one for logging
+			artifactListForLogging.add(ASDCElementInfo.createElementFromVfResourceStructure(vfResourceStructure));
+			
+			catalogDB.saveOrUpdateVnfResource(vfResourceStructure.getCatalogVnfResource());
+			catalogDB.saveService(vfResourceStructure.getCatalogService());
+			
+			for (VfModuleStructure vfModuleStructure : vfResourceStructure.getVfModuleStructure()) {
+
+				// Here we set the right db structure according to the Catalog
+				// DB
+
+				// We expect only one MAIN HEAT per VFMODULE
+				// we can also obtain from it the Env ArtifactInfo, that's why
+				// we
+				// get the Main IArtifactInfo
+
+				HeatTemplate heatMainTemplate = null;
+				HeatEnvironment heatEnv = null;
+				
+				HeatTemplate heatVolumeTemplate = null;
+				HeatEnvironment heatVolumeEnv = null;
+				
+				if (vfModuleStructure.getArtifactsMap().containsKey(ASDCConfiguration.HEAT)) {
+					IArtifactInfo mainEnvArtifactInfo = vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT)
+							.get(0).getArtifactInfo().getGeneratedArtifact();
+					
+					// MAIN HEAT
+					heatMainTemplate = (HeatTemplate) vfModuleStructure.getArtifactsMap()
+							.get(ASDCConfiguration.HEAT).get(0).getCatalogObject();
+
+					// Add this one for logging
+					artifactListForLogging.add(ASDCElementInfo
+							.createElementFromVfArtifactInfo(vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT).get(0).getArtifactInfo()));
+					
+					catalogDB.saveHeatTemplate(heatMainTemplate, heatMainTemplate.getParameters());
+					// Indicate we have deployed it in the DB
+					vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT).get(0).incrementDeployedInDB();
+					
+					
+					// VOLUME HEAT
+					// We expect only one VOL HEAT per VFMODULE
+					// we can also obtain from it the Env ArtifactInfo, that's why
+					// we get the Volume IArtifactInfo
+				
+					if (vfModuleStructure.getArtifactsMap().containsKey(ASDCConfiguration.HEAT_VOL)) {
+						IArtifactInfo volEnvArtifactInfo = vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT_VOL).get(0)
+								.getArtifactInfo().getGeneratedArtifact();
+		
+						heatVolumeTemplate = (HeatTemplate) vfModuleStructure.getArtifactsMap()
+								.get(ASDCConfiguration.HEAT_VOL).get(0).getCatalogObject();
+					
+						// Add this one for logging
+						artifactListForLogging.add(ASDCElementInfo.createElementFromVfArtifactInfo(vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT_VOL).get(0).getArtifactInfo()));
+
+						catalogDB.saveHeatTemplate(heatVolumeTemplate, heatVolumeTemplate.getParameters());
+						// Indicate we have deployed it in the DB
+						vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT_VOL).get(0).incrementDeployedInDB();
+						
+						if (volEnvArtifactInfo != null) {
+							heatVolumeEnv = (HeatEnvironment) vfResourceStructure.getArtifactsMapByUUID()
+									.get(volEnvArtifactInfo.getArtifactUUID()).getCatalogObject();
+
+							// Add this one for logging
+							artifactListForLogging.add(ASDCElementInfo.createElementFromVfArtifactInfo(volEnvArtifactInfo));
+														
+							catalogDB.saveHeatEnvironment(heatVolumeEnv);
+							// Indicate we have deployed it in the DB
+							vfResourceStructure.getArtifactsMapByUUID().get(volEnvArtifactInfo.getArtifactUUID()).incrementDeployedInDB();
+						}
+						
+					}
+					
+					// NESTED HEAT
+					// Here we expect many HEAT_NESTED template to be there
+					// check first if we really have nested heat templates
+					if (vfModuleStructure.getArtifactsMap().containsKey(ASDCConfiguration.HEAT_NESTED)) {
+						for (VfModuleArtifact heatNestedArtifact : vfModuleStructure.getArtifactsMap()
+								.get(ASDCConfiguration.HEAT_NESTED)) {
+	
+							// Check if this nested is well referenced by the MAIN HEAT
+							String parentArtifactType = VfResourceInstaller.identifyParentOfNestedTemplate(vfModuleStructure,heatNestedArtifact);
+							HeatTemplate heatNestedTemplate = (HeatTemplate) heatNestedArtifact.getCatalogObject();
+							
+							if (parentArtifactType != null) {
+														
+								switch (parentArtifactType) {
+									case ASDCConfiguration.HEAT:
+										
+										// Add this one for logging
+										artifactListForLogging.add(ASDCElementInfo.createElementFromVfArtifactInfo(heatNestedArtifact.getArtifactInfo()));
+								
+										catalogDB.saveNestedHeatTemplate (heatMainTemplate.getId(), heatNestedTemplate, heatNestedTemplate.getTemplateName());
+										// Indicate we have deployed it in the DB
+										heatNestedArtifact.incrementDeployedInDB();
+										break;
+									case ASDCConfiguration.HEAT_VOL:
+										
+										// Add this one for logging
+										artifactListForLogging.add(ASDCElementInfo.createElementFromVfArtifactInfo(heatNestedArtifact.getArtifactInfo()));
+										catalogDB.saveNestedHeatTemplate (heatVolumeTemplate.getId(), heatNestedTemplate, heatNestedTemplate.getTemplateName());
+										// Indicate we have deployed it in the DB
+										heatNestedArtifact.incrementDeployedInDB();
+										break;
+										
+									default:
+										break;
+
+								}
+							} else { // Assume it belongs to HEAT MAIN
+								// Add this one for logging
+								artifactListForLogging.add(ASDCElementInfo.createElementFromVfArtifactInfo(heatNestedArtifact.getArtifactInfo()));
+						
+								catalogDB.saveNestedHeatTemplate (heatMainTemplate.getId(), heatNestedTemplate, heatNestedTemplate.getTemplateName());
+								// Indicate we have deployed it in the DB
+								heatNestedArtifact.incrementDeployedInDB();
+							}
+						}
+					}
+					
+					if (mainEnvArtifactInfo != null) {
+						heatEnv = (HeatEnvironment) vfResourceStructure.getArtifactsMapByUUID()
+								.get(mainEnvArtifactInfo.getArtifactUUID()).getCatalogObject();
+
+						// Add this one for logging
+						artifactListForLogging.add(ASDCElementInfo.createElementFromVfArtifactInfo(mainEnvArtifactInfo));
+												
+						catalogDB.saveHeatEnvironment(heatEnv);
+						// Indicate we have deployed it in the DB
+						vfResourceStructure.getArtifactsMapByUUID().get(mainEnvArtifactInfo.getArtifactUUID()).incrementDeployedInDB();
+					}
+					
+				}
+		
+					
+				// here we expect one VFModule to be there
+				VfResourceInstaller.createVfModule(vfModuleStructure,heatMainTemplate, heatVolumeTemplate, heatEnv, heatVolumeEnv);
+				VfModule vfModule = vfModuleStructure.getCatalogVfModule();
+
+				// Add this one for logging
+				artifactListForLogging.add(ASDCElementInfo.createElementFromVfModuleStructure(vfModuleStructure));
+				
+				catalogDB.saveOrUpdateVfModule(vfModule);
+
+				// Here we expect many HEAT_TEMPLATE files to be there
+				if (vfModuleStructure.getArtifactsMap().containsKey(ASDCConfiguration.HEAT_ARTIFACT)) {
+					for (VfModuleArtifact heatArtifact : vfModuleStructure.getArtifactsMap()
+							.get(ASDCConfiguration.HEAT_ARTIFACT)) {
+	
+						HeatFiles heatFile = (HeatFiles) heatArtifact.getCatalogObject();
+											
+						// Add this one for logging
+						artifactListForLogging.add(ASDCElementInfo.createElementFromVfArtifactInfo(heatArtifact.getArtifactInfo()));
+					
+						
+						catalogDB.saveVfModuleToHeatFiles (vfModule.getId(), heatFile);
+						// Indicate we will deploy it in the DB
+						heatArtifact.incrementDeployedInDB();
+					}
+				}
+
+			}
+			
+			catalogDB.commit();
+			vfResourceStructure.setSuccessfulDeployment();
+			
+		} catch (Exception e) {
+
+			Throwable dbExceptionToCapture = e;
+			while (!(dbExceptionToCapture instanceof ConstraintViolationException || dbExceptionToCapture instanceof LockAcquisitionException)
+					&& (dbExceptionToCapture.getCause() != null)) {
+				dbExceptionToCapture = dbExceptionToCapture.getCause();
+			}
+
+			if (dbExceptionToCapture instanceof ConstraintViolationException || dbExceptionToCapture instanceof LockAcquisitionException) {
+				logger.warn(MessageEnum.ASDC_ARTIFACT_ALREADY_DEPLOYED, vfResourceStructure.getResourceInstance().getResourceName(),
+						vfResourceStructure.getNotification().getServiceVersion(), "", "", MsoLogger.ErrorCode.DataError, "Exception - ASCDC Artifact already deployed", e);
+			} else {
+				String endEvent = "Exception caught during installation of the VFResource. Transaction rollback.";
+				String elementToLog = (artifactListForLogging.size() > 0 ? artifactListForLogging.get(artifactListForLogging.size()-1).toString() : "No element listed");
+				logger.error(MessageEnum.ASDC_ARTIFACT_INSTALL_EXC, elementToLog, "", "", MsoLogger.ErrorCode.DataError, "Exception caught during installation of the VFResource. Transaction rollback", e);
+				catalogDB.rollback();
+				throw new ArtifactInstallerException(
+						"Exception caught during installation of the VFResource. Transaction rollback.", e);
+			}
+
+		} finally {
+			catalogDB.close();
+			// Debug log the whole collection...
+			logger.debug(artifactListForLogging.toString());
+		}
+
+	}
+	
+	private static String identifyParentOfNestedTemplate(VfModuleStructure vfModuleStructure,VfModuleArtifact heatNestedArtifact) {
+
+		if (vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT) != null 
+				&& vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT).get(0).getArtifactInfo().getRelatedArtifacts() != null) {
+			for (IArtifactInfo unknownArtifact : vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT).get(0)
+					.getArtifactInfo().getRelatedArtifacts()) {
+				if (heatNestedArtifact.getArtifactInfo().getArtifactUUID().equals(unknownArtifact.getArtifactUUID())) {
+					return ASDCConfiguration.HEAT;
+				}
+
+			}
+		} 
+		
+		if (vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT_VOL) != null 
+				&& vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT_VOL).get(0).getArtifactInfo().getRelatedArtifacts() != null) {
+			for (IArtifactInfo unknownArtifact:vfModuleStructure.getArtifactsMap().get(ASDCConfiguration.HEAT_VOL).get(0).getArtifactInfo().getRelatedArtifacts()) {
+				if (heatNestedArtifact.getArtifactInfo().getArtifactUUID().equals(unknownArtifact.getArtifactUUID())) {
+					return ASDCConfiguration.HEAT_VOL;
+				}
+			
+			}
+		}
+		
+		// Does not belong to anything
+		return null;
+			
+	}
+	
+	private static void createVnfResource(VfResourceStructure vfResourceStructure) {
+		VnfResource vnfResource = new VnfResource();
+		
+		vnfResource.setAsdcUuid(vfResourceStructure.getResourceInstance().getResourceUUID());
+		vnfResource.setDescription(vfResourceStructure.getNotification().getServiceDescription());
+		
+		vnfResource.setOrchestrationMode("HEAT");
+		// Set the version but Version is stored into ASDC_SERVICE_MODEL_VERSION
+		vnfResource.setVersion(BigDecimalVersion
+				.castAndCheckNotificationVersionToString(vfResourceStructure.getNotification().getServiceVersion()));
+		vnfResource.setVnfType(VfResourceInstaller.createVNFName(vfResourceStructure));
+		vnfResource.setModelVersion(BigDecimalVersion
+				.castAndCheckNotificationVersionToString(vfResourceStructure.getResourceInstance().getResourceVersion()));
+		
+		vnfResource.setModelInvariantUuid(vfResourceStructure.getResourceInstance().getResourceInvariantUUID());
+		vnfResource.setModelCustomizationName(vfResourceStructure.getResourceInstance().getResourceInstanceName());
+		vnfResource.setModelName(vfResourceStructure.getResourceInstance().getResourceName());
+		vnfResource.setServiceModelInvariantUUID(vfResourceStructure.getNotification().getServiceInvariantUUID());
+	
+		vfResourceStructure.setCatalogVnfResource(vnfResource);
+	}
+
+	private static void createVfModule(VfModuleStructure vfModuleStructure,HeatTemplate heatMain, HeatTemplate heatVolume,HeatEnvironment heatEnv, HeatEnvironment heatVolumeEnv) {
+		VfModule vfModule = new VfModule();
+		vfModule.setType(createVfModuleName(vfModuleStructure));
+		vfModule.setAsdcUuid(vfModuleStructure.getVfModuleMetadata().getVfModuleModelUUID());
+		vfModule.setDescription(vfModuleStructure.getVfModuleMetadata().getVfModuleModelDescription());
+
+		if (vfModuleStructure.getVfModuleMetadata().isBase()) {
+			vfModule.setIsBase(1);
+		} else {
+			vfModule.setIsBase(0);
+		}
+
+		vfModule.setModelInvariantUuid(vfModuleStructure.getVfModuleMetadata().getVfModuleModelInvariantUUID());
+		vfModule.setModelName(vfModuleStructure.getVfModuleMetadata().getVfModuleModelName());
+		
+		vfModule.setVersion(BigDecimalVersion.castAndCheckNotificationVersionToString(vfModuleStructure.getParentVfResource().getNotification().getServiceVersion()));
+		vfModule.setModelVersion(BigDecimalVersion.castAndCheckNotificationVersionToString(
+				vfModuleStructure.getVfModuleMetadata().getVfModuleModelVersion()));
+	
+		vfModuleStructure.setCatalogVfModule(vfModule);
+		
+		VfResourceInstaller.createVfModuleLinks(vfModule, vfModuleStructure.getParentVfResource().getCatalogVnfResource(), heatMain,heatVolume, heatEnv,heatVolumeEnv);
+	}
+
+	private static void createVfModuleLinks(VfModule vfModule, VnfResource vnfResource, HeatTemplate heatMain,
+			HeatTemplate heatVolume, HeatEnvironment heatEnv, HeatEnvironment heatVolumeEnv) {
+		
+		if (heatMain !=null) {
+			vfModule.setTemplateId(heatMain.getId());
+		}
+		if (heatEnv != null) {
+			vfModule.setEnvironmentId(heatEnv.getId());
+		}
+		if (heatVolume != null) {
+			vfModule.setVolTemplateId(heatVolume.getId());
+		}
+		if (heatVolumeEnv != null) {
+			vfModule.setVolEnvironmentId(heatVolumeEnv.getId());
+		}
+		
+		vfModule.setVnfResourceId(vnfResource.getId());
+
+	}
+
+	private static Set<HeatTemplateParam> extractHeatTemplateParameters(String yamlFile) {
+
+		// Scan the payload downloadResult and extract the HeatTemplate
+		// parameters
+		YamlEditor yamlEditor = new YamlEditor(yamlFile.getBytes());
+		return yamlEditor.getParameterList();
+
+	}
+
+	
+	public static String verifyTheFilePrefixInArtifacts(String filebody, VfResourceStructure vfResourceStructure, List<String> listTypes) {
+		String newFileBody = filebody;
+		for (VfModuleArtifact moduleArtifact:vfResourceStructure.getArtifactsMapByUUID().values()) {
+			
+			if (listTypes.contains(moduleArtifact.getArtifactInfo().getArtifactType())) {
+				
+				newFileBody = verifyTheFilePrefixInString(newFileBody,moduleArtifact.getArtifactInfo().getArtifactName());
+			}
+		}
+		return newFileBody;
+	}
+	
+	public static String verifyTheFilePrefixInString(final String body, final String filenameToVerify) {
+		
+		String needlePrefix = "file:///";
+		String prefixedFilenameToVerify = needlePrefix+filenameToVerify;
+		
+		if ((body == null) || (body.length() == 0) || (filenameToVerify == null) || (filenameToVerify.length() == 0)) { 
+			return body; 
+		} 
+ 
+		StringBuffer sb = new StringBuffer(body.length()); 
+ 
+		int currentIndex = 0; 
+		int startIndex = 0; 
+ 
+		while (currentIndex != -1) { 
+			startIndex = currentIndex; 
+			currentIndex = body.indexOf(prefixedFilenameToVerify, startIndex); 
+ 
+			if (currentIndex == -1) { 
+				break; 
+			} 
+ 
+			// We append from the startIndex up to currentIndex (start of File Name) 
+			sb.append(body.substring(startIndex, currentIndex)); 
+			sb.append(filenameToVerify); 
+ 
+			currentIndex += prefixedFilenameToVerify.length(); 
+		} 
+ 
+		sb.append(body.substring(startIndex)); 
+ 
+		return sb.toString();
+	}
+	
+	private static void createHeatTemplateFromArtifact(VfResourceStructure vfResourceStructure,
+			VfModuleArtifact vfModuleArtifact) {
+		HeatTemplate heatTemplate = new HeatTemplate();
+
+		// TODO Set the label
+		heatTemplate.setAsdcLabel("label");
+		// Use the ResourceName of the ASDC template because the HEAT could be
+		// reused
+		heatTemplate.setAsdcResourceName(vfResourceStructure.getResourceInstance().getResourceName());
+		heatTemplate.setAsdcUuid(vfModuleArtifact.getArtifactInfo().getArtifactUUID());
+		
+		List<String> typeList = new ArrayList<String>();
+		typeList.add(ASDCConfiguration.HEAT_NESTED);
+		typeList.add(ASDCConfiguration.HEAT_ARTIFACT);
+		
+		heatTemplate.setTemplateBody(verifyTheFilePrefixInArtifacts(vfModuleArtifact.getResult(),vfResourceStructure,typeList));
+		heatTemplate.setTemplateName(vfModuleArtifact.getArtifactInfo().getArtifactName());
+
+		if (vfModuleArtifact.getArtifactInfo().getArtifactTimeout() != null) {
+			heatTemplate.setTimeoutMinutes(vfModuleArtifact.getArtifactInfo().getArtifactTimeout());
+		} else {
+			heatTemplate.setTimeoutMinutes(240);
+		}
+
+		heatTemplate.setDescription(vfModuleArtifact.getArtifactInfo().getArtifactDescription());
+		heatTemplate.setVersion(BigDecimalVersion
+				.castAndCheckNotificationVersionToString(vfModuleArtifact.getArtifactInfo().getArtifactVersion()));
+		Set<HeatTemplateParam> heatParam = VfResourceInstaller
+				.extractHeatTemplateParameters(vfModuleArtifact.getResult());
+		heatTemplate.setParameters(heatParam);
+
+		vfModuleArtifact.setCatalogObject(heatTemplate);
+	}
+
+	private static void createHeatEnvFromArtifact(VfResourceStructure vfResourceStructure,
+			VfModuleArtifact vfModuleArtifact) {
+		HeatEnvironment heatEnvironment = new HeatEnvironment();
+
+		heatEnvironment.setName(vfModuleArtifact.getArtifactInfo().getArtifactName());
+		// TODO Set the label
+		heatEnvironment.setAsdcLabel("Label");
+		
+		List<String> typeList = new ArrayList<String>();
+		typeList.add(ASDCConfiguration.HEAT);
+		typeList.add(ASDCConfiguration.HEAT_VOL);
+		
+		heatEnvironment.setEnvironment(verifyTheFilePrefixInArtifacts(vfModuleArtifact.getResult(),vfResourceStructure,typeList));
+		heatEnvironment.setAsdcUuid(vfModuleArtifact.getArtifactInfo().getArtifactUUID());
+		heatEnvironment.setDescription(vfModuleArtifact.getArtifactInfo().getArtifactDescription());
+		heatEnvironment.setVersion(BigDecimalVersion
+				.castAndCheckNotificationVersionToString(vfModuleArtifact.getArtifactInfo().getArtifactVersion()));
+		heatEnvironment.setAsdcResourceName(VfResourceInstaller.createVNFName(vfResourceStructure));
+
+		vfModuleArtifact.setCatalogObject(heatEnvironment);
+		
+	}
+
+	private static void createHeatFileFromArtifact(VfResourceStructure vfResourceStructure,
+			VfModuleArtifact vfModuleArtifact) {
+
+		HeatFiles heatFile = new HeatFiles();
+		// TODO Set the label
+		heatFile.setAsdcLabel("Label");
+		heatFile.setAsdcUuid(vfModuleArtifact.getArtifactInfo().getArtifactUUID());
+		heatFile.setDescription(vfModuleArtifact.getArtifactInfo().getArtifactDescription());
+		heatFile.setFileBody(vfModuleArtifact.getResult());
+		heatFile.setFileName(vfModuleArtifact.getArtifactInfo().getArtifactName());
+		heatFile.setVersion(BigDecimalVersion
+				.castAndCheckNotificationVersionToString(vfModuleArtifact.getArtifactInfo().getArtifactVersion()));
+
+		heatFile.setAsdcResourceName(vfResourceStructure.getResourceInstance().getResourceName());
+		vfModuleArtifact.setCatalogObject(heatFile);
+		
+	}
+
+	private static void createService(VfResourceStructure vfResourceStructure) {
+		
+		Service service = new Service();
+		service.setDescription(vfResourceStructure.getNotification().getServiceDescription());
+		service.setServiceName(vfResourceStructure.getNotification().getServiceName());
+		service.setServiceNameVersionId(vfResourceStructure.getNotification().getServiceUUID());
+		service.setVersion(vfResourceStructure.getNotification().getServiceVersion());
+		service.setModelInvariantUUID(vfResourceStructure.getNotification().getServiceInvariantUUID());
+				
+		vfResourceStructure.setCatalogService(service);
+	}
+	
+	
+	private static String createVNFName(VfResourceStructure vfResourceStructure) {
+
+		return vfResourceStructure.getNotification().getServiceName() + "/" + vfResourceStructure.getResourceInstance().getResourceInstanceName();
+	}
+
+	private static String createVfModuleName(VfModuleStructure vfModuleStructure) {
+		
+		return createVNFName(vfModuleStructure.getParentVfResource())+"::"+vfModuleStructure.getVfModuleMetadata().getVfModuleModelName();
+	}
+
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/ASDCNotificationLogging.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/ASDCNotificationLogging.java
new file mode 100644
index 0000000..312613d
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/ASDCNotificationLogging.java
@@ -0,0 +1,335 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.util;
+
+
+import java.util.List;
+
+import org.openecomp.sdc.api.notification.IArtifactInfo;
+import org.openecomp.sdc.api.notification.INotificationData;
+import org.openecomp.sdc.api.notification.IResourceInstance;
+import org.openecomp.sdc.api.notification.IVfModuleMetadata;
+
+public class ASDCNotificationLogging {
+
+	public static String dumpASDCNotification(INotificationData asdcNotification) {
+		
+		if (asdcNotification == null) {
+			return "NULL";
+		}
+		StringBuffer buffer = new StringBuffer("ASDC Notification:");
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("DistributionID:");
+		buffer.append(testNull(asdcNotification.getDistributionID()));
+		buffer.append(System.lineSeparator());
+		
+		
+		buffer.append("ServiceName:");
+		buffer.append(testNull(asdcNotification.getServiceName()));
+		buffer.append(System.lineSeparator());
+		
+		
+		buffer.append("ServiceVersion:");
+		buffer.append(testNull(asdcNotification.getServiceVersion()));
+		buffer.append(System.lineSeparator());
+		
+		
+		buffer.append("ServiceUUID:");
+		buffer.append(testNull(asdcNotification.getServiceUUID()));
+		buffer.append(System.lineSeparator());
+	
+		
+		buffer.append("ServiceInvariantUUID:");
+		buffer.append(testNull(asdcNotification.getServiceInvariantUUID()));
+		buffer.append(System.lineSeparator());
+		
+		
+		buffer.append("ServiceDescription:");
+		buffer.append(testNull(asdcNotification.getServiceDescription()));
+		buffer.append(System.lineSeparator());
+	
+		
+		buffer.append("Service Artifacts List:");
+		buffer.append(System.lineSeparator());
+		buffer.append(testNull(dumpArtifactInfoList(asdcNotification.getServiceArtifacts())));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("Resource Instances List:");
+		buffer.append(System.lineSeparator());
+		buffer.append(testNull(dumpASDCResourcesList(asdcNotification)));
+		buffer.append(System.lineSeparator());
+		
+		
+		return buffer.toString();
+	}
+	
+	public static String dumpVfModuleMetaDataList(List<IVfModuleMetadata> moduleMetaDataList) {
+		if (moduleMetaDataList == null ) {
+			return null;
+		}
+		
+		StringBuffer buffer = new StringBuffer();		
+		buffer.append("{");
+		
+		for (IVfModuleMetadata moduleMetaData:moduleMetaDataList) {
+			buffer.append(System.lineSeparator());
+			buffer.append(testNull(dumpVfModuleMetaData(moduleMetaData)));
+			buffer.append(System.lineSeparator());
+			buffer.append(",");
+			
+		}
+		buffer.replace(buffer.length()-1,buffer.length(), System.lineSeparator());
+		buffer.append("}");
+		buffer.append(System.lineSeparator());
+		
+		return buffer.toString();
+	}
+	
+	private static String dumpVfModuleMetaData(IVfModuleMetadata moduleMetaData) {
+				
+		if (moduleMetaData == null ) {
+			return "NULL";
+		}
+		
+		StringBuffer buffer = new StringBuffer("VfModuleMetaData:");
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("VfModuleModelName:");
+		buffer.append(testNull(moduleMetaData.getVfModuleModelName()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("VfModuleModelVersion:");
+		buffer.append(testNull(moduleMetaData.getVfModuleModelVersion()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("VfModuleModelUUID:");
+		buffer.append(testNull(moduleMetaData.getVfModuleModelUUID()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("VfModuleModelInvariantUUID:");
+		buffer.append(testNull(moduleMetaData.getVfModuleModelInvariantUUID()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("VfModuleModelDescription:");
+		buffer.append(testNull(moduleMetaData.getVfModuleModelDescription()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("Artifacts UUID List:");
+		
+		if (moduleMetaData.getArtifacts() != null) {
+			buffer.append("{");
+			
+			for (String artifactUUID:moduleMetaData.getArtifacts()) {
+				buffer.append(System.lineSeparator());
+				buffer.append(testNull(artifactUUID));
+				buffer.append(System.lineSeparator());
+				buffer.append(",");
+			}
+			buffer.replace(buffer.length()-1,buffer.length(), System.lineSeparator());
+			buffer.append("}");
+			buffer.append(System.lineSeparator());
+		} else {
+			buffer.append("NULL");
+		}
+		
+		
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("isBase:");
+		buffer.append(moduleMetaData.isBase());
+		buffer.append(System.lineSeparator());
+		
+		return buffer.toString();
+	}
+	
+	private static String testNull(Object object) {
+		if (object == null) {
+			return "NULL";
+		} else if (object instanceof Integer) {
+			return object.toString();
+		} else if (object instanceof String) {
+			return (String)object;
+		} else {
+			return "Type not recognized";
+		}
+	}
+	
+	private static String dumpASDCResourcesList(INotificationData asdcNotification) {
+		if (asdcNotification == null || asdcNotification.getResources() == null) {
+			return null;
+		}
+		
+		StringBuffer buffer = new StringBuffer();		
+		buffer.append("{");
+		
+		for (IResourceInstance resourceInstanceElem:asdcNotification.getResources()) {
+			buffer.append(System.lineSeparator());
+			buffer.append(testNull(dumpASDCResourceInstance(resourceInstanceElem)));
+			buffer.append(System.lineSeparator());
+			buffer.append(",");
+		}
+		buffer.replace(buffer.length()-1,buffer.length(), System.lineSeparator());
+		buffer.append("}");
+		buffer.append(System.lineSeparator());
+		
+		return buffer.toString();
+		
+	}
+	
+	private static String dumpASDCResourceInstance(IResourceInstance resourceInstance) {
+		
+		if (resourceInstance == null) {
+			return null;
+		}
+		
+		StringBuffer buffer = new StringBuffer("Resource Instance Info:");
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ResourceInstanceName:");
+		buffer.append(testNull(resourceInstance.getResourceInstanceName()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ResourceInvariantUUID:");
+		buffer.append(testNull(resourceInstance.getResourceInvariantUUID()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ResourceName:");
+		buffer.append(testNull(resourceInstance.getResourceName()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ResourceType:");
+		buffer.append(testNull(resourceInstance.getResourceType()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ResourceUUID:");
+		buffer.append(testNull(resourceInstance.getResourceUUID()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ResourceVersion:");
+		buffer.append(testNull(resourceInstance.getResourceVersion()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("Resource Artifacts List:");
+		buffer.append(System.lineSeparator());
+		buffer.append(testNull(dumpArtifactInfoList(resourceInstance.getArtifacts())));
+		buffer.append(System.lineSeparator());
+		
+		return buffer.toString();
+		
+	}
+	
+	
+	private static String dumpArtifactInfoList(List<IArtifactInfo> artifactsList) {
+		
+		if (artifactsList == null || artifactsList.isEmpty()) {
+			return null;
+		}
+		
+		StringBuffer buffer = new StringBuffer();		
+		buffer.append("{");
+		for (IArtifactInfo artifactInfoElem:artifactsList) {
+			buffer.append(System.lineSeparator());
+			buffer.append(testNull(dumpASDCArtifactInfo(artifactInfoElem)));
+			buffer.append(System.lineSeparator());
+			buffer.append(",");
+			
+		}
+		buffer.replace(buffer.length()-1,buffer.length(), System.lineSeparator());
+		buffer.append("}");
+		buffer.append(System.lineSeparator());
+		
+		return buffer.toString();
+	}
+	
+	private static String dumpASDCArtifactInfo(IArtifactInfo artifactInfo) {
+		
+		if (artifactInfo == null) {
+			return null;
+		}
+		
+		StringBuffer buffer = new StringBuffer("Service Artifacts Info:");
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ArtifactName:");
+		buffer.append(testNull(artifactInfo.getArtifactName()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ArtifactVersion:");
+		buffer.append(testNull(artifactInfo.getArtifactVersion()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ArtifactType:");
+		buffer.append(testNull(artifactInfo.getArtifactType()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ArtifactDescription:");
+		buffer.append(testNull(artifactInfo.getArtifactDescription()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ArtifactTimeout:");
+		buffer.append(testNull(artifactInfo.getArtifactTimeout()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ArtifactURL:");
+		buffer.append(testNull(artifactInfo.getArtifactURL()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ArtifactUUID:");
+		buffer.append(testNull(artifactInfo.getArtifactUUID()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("ArtifactChecksum:");
+		buffer.append(testNull(artifactInfo.getArtifactChecksum()));
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("GeneratedArtifact:");
+		buffer.append("{");
+		buffer.append(testNull(dumpASDCArtifactInfo(artifactInfo.getGeneratedArtifact())));
+		buffer.append(System.lineSeparator());
+		buffer.append("}");
+		buffer.append(System.lineSeparator());
+		
+		buffer.append("RelatedArtifacts:");
+		
+		
+		if (artifactInfo.getRelatedArtifacts() != null) {
+			buffer.append("{");
+			buffer.append(System.lineSeparator());
+			for (IArtifactInfo artifactInfoElem:artifactInfo.getRelatedArtifacts()) {
+							
+				buffer.append(testNull(dumpASDCArtifactInfo(artifactInfoElem)));
+				buffer.append(System.lineSeparator());
+				buffer.append(",");
+			
+			}
+			buffer.replace(buffer.length()-1,buffer.length(), System.lineSeparator());
+			buffer.append("}");
+			buffer.append(System.lineSeparator());
+		} else {
+			buffer.append("NULL");
+		}
+		
+		buffer.append(System.lineSeparator());
+		
+		return buffer.toString();
+	}
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/NotificationLogging.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/NotificationLogging.java
new file mode 100644
index 0000000..b45cf06
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/NotificationLogging.java
@@ -0,0 +1,168 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+
+package org.openecomp.mso.asdc.util;
+
+
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.openecomp.sdc.api.notification.INotificationData;
+
+
+public class NotificationLogging implements InvocationHandler {
+	
+	private static Map<Object, List<Method>> objectMethodsToLog = new HashMap<>();
+
+	private static InvocationHandler handler = new InvocationHandler() {
+		@Override
+		public Object invoke(Object arg0, Method arg1, Object[] arg2)
+				throws Throwable {
+			List<Method> methods = objectMethodsToLog.get(arg0);
+			if ((methods == null) || (methods.isEmpty())) {
+				// Do nothing for now...
+				return null;
+			}
+			methods.add(arg1);
+			return arg1.invoke(arg0, arg2);
+		}
+	};
+	
+	public static InvocationHandler getHandler() {
+		return handler;
+	}
+	
+	/**
+	 * 
+	 */
+	private NotificationLogging() {}
+	
+	private static final String[] GETTER_PREFIXES = { "get", "is" };
+	
+	public static String logNotification(INotificationData iNotif) {
+		if (iNotif == null) {
+			return "NULL";
+		}
+
+		Class<? extends INotificationData> clazz = iNotif.getClass();
+		
+		Method[] declaredMethods = clazz.getDeclaredMethods();
+		
+		if (declaredMethods == null || declaredMethods.length == 0) {
+			return "EMPTY"; // No declared methods in this class !!!
+		}
+		
+		StringBuffer buffer = new StringBuffer("ASDC Notification:");
+		buffer.append(System.lineSeparator());
+		
+		for (Method m : declaredMethods) {
+			if ((m != null) && isGetter(m)) {
+				for (String prefix : GETTER_PREFIXES) {
+					if (m.getName().startsWith(prefix)) {
+						buffer.append(m.getName().substring(prefix.length()));
+						break;
+					}
+				}
+				try {
+					buffer.append(testNull(m.invoke(iNotif, (Object[])null)));
+				} catch (IllegalAccessException | IllegalArgumentException
+						| InvocationTargetException e) {
+					buffer.append("UNREADABLE");
+				}
+				buffer.append(System.lineSeparator());
+			}
+		}
+		
+		return buffer.toString();
+	}
+	
+	private static final boolean isGetter(Method method) {
+
+		// Must start with a valid (and known) prefix
+		boolean prefixFound = false;
+		for (String prefix : GETTER_PREFIXES) {
+			if (method.getName().startsWith(prefix)) {
+				prefixFound = true;
+				break;
+			}
+		}
+		if (!prefixFound) {
+			return false;
+		}
+
+		// Must not take any input arguments
+		if (method.getParameterTypes().length != 0) {
+			return false;  
+		}
+		
+		// Must not have return type 'void'
+		if (void.class.equals(method.getReturnType())) {
+			return false;
+		}
+		
+		// Must be public
+		if (!Modifier.isPublic(method.getModifiers())) {
+			return false;
+		}
+		
+		return true;
+	}
+	
+	private static String testNull(Object object) {
+		if (object == null) {
+			return "NULL";
+		} else if (object instanceof Integer) {
+			return object.toString();
+		} else if (object instanceof String) {
+			return (String) object;
+		} else {
+			return "Type not recognized";
+		}
+	}
+	
+	private static void registerForLog(INotificationData objectToLog) {
+		INotificationData proxy = (INotificationData) Proxy.newProxyInstance(
+				INotificationData.class.getClassLoader(),
+				new Class[] { INotificationData.class },
+				NotificationLogging.getHandler());
+		objectMethodsToLog.put(proxy, new ArrayList<Method>());
+	}
+	
+	private static <T> void methodToLog(T methodCall) {
+		//
+	}
+
+	@Override
+	public Object invoke(Object proxy, Method method, Object[] args)
+			throws Throwable {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/ToLog.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/ToLog.java
new file mode 100644
index 0000000..524cc97
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/ToLog.java
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+
+package org.openecomp.mso.asdc.util;
+
+
+
+
+public @interface ToLog {
+
+}
diff --git a/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/YamlEditor.java b/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/YamlEditor.java
new file mode 100644
index 0000000..773ff86
--- /dev/null
+++ b/asdc-controller/src/main/java/org/openecomp/mso/asdc/util/YamlEditor.java
@@ -0,0 +1,177 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.mso.asdc.util;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.yaml.snakeyaml.Yaml;
+
+import org.openecomp.mso.db.catalog.beans.HeatTemplateParam;
+
+public class YamlEditor {
+
+    private static final String REFER_PATTERN = "file:///";
+    private Map <String, Object> yml;
+    private Yaml yaml = new Yaml ();
+
+    public YamlEditor () {
+
+    }
+
+    public YamlEditor (byte[] body) {
+        init (body);
+    }
+
+    @SuppressWarnings("unchecked")
+    private synchronized void init (byte[] body) {
+        InputStream input = new ByteArrayInputStream (body);
+        yml = (Map <String, Object>) yaml.load (input);
+    }
+
+    public synchronized List <String> getYamlNestedFileResourceTypeList () {
+        List <String> typeList = new ArrayList <String> ();
+
+        @SuppressWarnings("unchecked")
+        Map <String, Object> resourceMap = (Map <String, Object>) yml.get ("resources");
+        Iterator <Entry <String, Object>> it = resourceMap.entrySet ().iterator ();
+        while (it.hasNext ()) {
+            Map.Entry <String, Object> pair = it.next ();
+            @SuppressWarnings("unchecked")
+            Map <String, String> resourceEntry = (Map <String, String>) pair.getValue ();
+            String type = resourceEntry.get ("type");
+
+            if (type.contains (REFER_PATTERN)) {
+                typeList.add (type);
+            }
+            it.remove (); // avoids a ConcurrentModificationException
+        }
+        return typeList;
+    }
+    
+    public synchronized List <String> getYamlResourceTypeList () {
+        List <String> typeList = new ArrayList <String> ();
+
+        @SuppressWarnings("unchecked")
+        Map <String, Object> resourceMap = (Map <String, Object>) yml.get ("resources");
+        Iterator <Entry <String, Object>> it = resourceMap.entrySet ().iterator ();
+        while (it.hasNext ()) {
+            Map.Entry <String, Object> pair = it.next ();
+            @SuppressWarnings("unchecked")
+            Map <String, String> resourceEntry = (Map <String, String>) pair.getValue ();
+            typeList.add (resourceEntry.get ("type"));
+        }
+        return typeList;
+    }    
+
+    // Generate the parameter list based on the Heat Template
+    // Based on the email from Ella Kvetny:
+    // Within Heat Template, under parameters catalog, it might indicate the default value of the parameter
+    // If default value exist, the parameter is not mandatory, otherwise its value should be set
+    public synchronized Set <HeatTemplateParam> getParameterList () {
+        Set <HeatTemplateParam> paramSet = new HashSet <HeatTemplateParam> ();
+        @SuppressWarnings("unchecked")
+        Map <String, Object> resourceMap = (Map <String, Object>) yml.get ("parameters");
+        Iterator <Entry <String, Object>> it = resourceMap.entrySet ().iterator ();
+
+        while (it.hasNext ()) {
+            HeatTemplateParam param = new HeatTemplateParam ();
+            Map.Entry <String, Object> pair = it.next ();
+            @SuppressWarnings("unchecked")
+            Map <String, String> resourceEntry = (Map <String, String>) pair.getValue ();
+            
+            param.setParamName (pair.getKey ());
+            // System.out.println(pair.getKey()+":"+type);
+            if (resourceEntry.containsKey("default")) {
+                param.setRequired (false);
+            } else {
+                param.setRequired (true);
+            }
+            // Now set the type
+            String value = resourceEntry.get ("type");
+            param.setParamType (value);
+
+            paramSet.add (param);
+
+        }
+        return paramSet;
+
+    }
+
+    public synchronized void addParameterList (Set <HeatTemplateParam> heatSet) {
+
+        @SuppressWarnings("unchecked")
+        Map <String, Object> resourceMap = (Map <String, Object>) yml.get ("parameters");
+        if (resourceMap == null) {
+            resourceMap = new LinkedHashMap <String, Object> ();
+            this.yml.put ("parameters", resourceMap);
+        }
+        for (HeatTemplateParam heatParam : heatSet) {
+            Map <String, Object> paramInfo = new HashMap <String, Object> ();
+            paramInfo.put ("type", heatParam.getParamType ());
+
+            resourceMap.put (heatParam.getParamName (), paramInfo);
+        }
+
+        // this.yml.put("parameters", resourceMap);
+
+    }
+
+    public boolean isParentTemplate (String templateBody) {
+        return templateBody.contains (REFER_PATTERN);
+    }
+
+    public boolean verifyTemplate () {
+        // Verify whether the heat template is for Vnf Resource
+        // We don't support other template installation yet
+
+        return true;
+    }
+
+    public String encode (Map <String, Object> content) {
+        return yaml.dump (content);
+    }
+
+    public synchronized String encode () {
+        return this.yaml.dump (this.yml);
+    }
+
+    /**
+     * This method return the YAml file as a string.
+     * 
+     */
+    @Override
+    public String toString () {
+
+        return encode ();
+    }
+
+}
diff --git a/asdc-controller/src/main/resources/config-key.properties b/asdc-controller/src/main/resources/config-key.properties
new file mode 100644
index 0000000..b6a0cde
--- /dev/null
+++ b/asdc-controller/src/main/resources/config-key.properties
@@ -0,0 +1,21 @@
+###
+# ============LICENSE_START=======================================================
+# ECOMP MSO
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 
+#      http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+###
+
+asdc.config.key=566B754875657232314F5548556D3665