Send sdc notifs
[clamp.git] / src / main / java / org / onap / clamp / clds / sdc / controller / SdcSingleController.java
index 21deb64..1885cc4 100644 (file)
-/*-\r
- * ============LICENSE_START=======================================================\r
- * ONAP CLAMP\r
- * ================================================================================\r
- * Copyright (C) 2018 AT&T Intellectual Property. All rights\r
- *                             reserved.\r
- * ================================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ============LICENSE_END============================================\r
- * ===================================================================\r
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
- */\r
-\r
-package org.onap.clamp.clds.sdc.controller;\r
-\r
-import com.att.eelf.configuration.EELFLogger;\r
-import com.att.eelf.configuration.EELFManager;\r
-\r
-import java.util.Date;\r
-import java.util.concurrent.ThreadLocalRandom;\r
-\r
-import org.onap.clamp.clds.config.ClampProperties;\r
-import org.onap.clamp.clds.config.sdc.SdcSingleControllerConfiguration;\r
-import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException;\r
-import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;\r
-import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException;\r
-import org.onap.clamp.clds.exception.sdc.controller.SdcDownloadException;\r
-import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException;\r
-import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;\r
-import org.onap.clamp.clds.sdc.controller.installer.CsarInstaller;\r
-import org.onap.clamp.clds.util.LoggingUtils;\r
-import org.onap.sdc.api.IDistributionClient;\r
-import org.onap.sdc.api.consumer.IDistributionStatusMessage;\r
-import org.onap.sdc.api.consumer.INotificationCallback;\r
-import org.onap.sdc.api.notification.IArtifactInfo;\r
-import org.onap.sdc.api.notification.INotificationData;\r
-import org.onap.sdc.api.results.IDistributionClientDownloadResult;\r
-import org.onap.sdc.api.results.IDistributionClientResult;\r
-import org.onap.sdc.impl.DistributionClientFactory;\r
-import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;\r
-import org.onap.sdc.utils.DistributionActionResultEnum;\r
-import org.onap.sdc.utils.DistributionStatusEnum;\r
-\r
-/**\r
- * This class handles one sdc controller defined in the config.\r
- */\r
-public class SdcSingleController {\r
-\r
-    private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcSingleController.class);\r
-    private boolean isSdcClientAutoManaged = false;\r
-    private CsarInstaller csarInstaller;\r
-    private ClampProperties refProp;\r
-    public static final String CONFIG_SDC_FOLDER = "sdc.csarFolder";\r
-    private int nbOfNotificationsOngoing = 0;\r
-    private SdcSingleControllerStatus controllerStatus = SdcSingleControllerStatus.STOPPED;\r
-    private SdcSingleControllerConfiguration sdcConfig;\r
-    private IDistributionClient distributionClient;\r
-\r
-    /**\r
-     * Inner class for Notification callback\r
-     */\r
-    private final class SdcNotificationCallBack implements INotificationCallback {\r
-\r
-        private SdcSingleController sdcController;\r
-\r
-        SdcNotificationCallBack(SdcSingleController controller) {\r
-            sdcController = controller;\r
-        }\r
-\r
-        /**\r
-         * This method can be called multiple times at the same moment. The\r
-         * controller must be thread safe !\r
-         */\r
-        @Override\r
-        public void activateCallback(INotificationData iNotif) {\r
-            Date startTime = new Date();\r
-            logger.info("Receive a callback notification in SDC, nb of resources: " + iNotif.getResources().size());\r
-            sdcController.treatNotification(iNotif);\r
-            LoggingUtils.setTimeContext(startTime, new Date());\r
-            LoggingUtils.setResponseContext("0", "SDC Notification received and processed successfully",\r
-                    this.getClass().getName());\r
-        }\r
-    }\r
-\r
-    public int getNbOfNotificationsOngoing() {\r
-        return nbOfNotificationsOngoing;\r
-    }\r
-\r
-    private void changeControllerStatusIdle() {\r
-        if (this.nbOfNotificationsOngoing > 1) {\r
-            --this.nbOfNotificationsOngoing;\r
-        } else {\r
-            this.nbOfNotificationsOngoing = 0;\r
-            this.controllerStatus = SdcSingleControllerStatus.IDLE;\r
-        }\r
-    }\r
-\r
-    protected final synchronized void changeControllerStatus(SdcSingleControllerStatus newControllerStatus) {\r
-        switch (newControllerStatus) {\r
-            case BUSY:\r
-                ++this.nbOfNotificationsOngoing;\r
-                this.controllerStatus = newControllerStatus;\r
-                break;\r
-            case IDLE:\r
-                this.changeControllerStatusIdle();\r
-                break;\r
-            default:\r
-                this.controllerStatus = newControllerStatus;\r
-                break;\r
-        }\r
-    }\r
-\r
-    public final synchronized SdcSingleControllerStatus getControllerStatus() {\r
-        return this.controllerStatus;\r
-    }\r
-\r
-    public SdcSingleController(ClampProperties clampProp, CsarInstaller csarInstaller,\r
-            SdcSingleControllerConfiguration sdcSingleConfig, boolean isClientAutoManaged) {\r
-        this.isSdcClientAutoManaged = isClientAutoManaged;\r
-        this.sdcConfig = sdcSingleConfig;\r
-        this.refProp = clampProp;\r
-        this.csarInstaller = csarInstaller;\r
-    }\r
-\r
-    /**\r
-     * This method initializes the SDC Controller and the SDC Client.\r
-     *\r
-     * @throws SdcControllerException\r
-     *             It throws an exception if the SDC Client cannot be\r
-     *             instantiated or if an init attempt is done when already\r
-     *             initialized\r
-     * @throws SdcParametersException\r
-     *             If there is an issue with the parameters provided\r
-     */\r
-    public void initSdc() throws SdcControllerException {\r
-        logger.info("Attempt to initialize the SDC Controller");\r
-        if (this.getControllerStatus() != SdcSingleControllerStatus.STOPPED) {\r
-            throw new SdcControllerException("The controller is already initialized, call the closeSDC method first");\r
-        }\r
-        if (this.distributionClient == null) {\r
-            distributionClient = DistributionClientFactory.createDistributionClient();\r
-        }\r
-        IDistributionClientResult result = this.distributionClient.init(sdcConfig, new SdcNotificationCallBack(this));\r
-        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {\r
-            logger.error("SDC distribution client init failed with reason:" + result.getDistributionMessageResult());\r
-            this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);\r
-            throw new SdcControllerException("Initialization of the SDC Controller failed with reason: "\r
-                    + result.getDistributionMessageResult());\r
-        }\r
-        result = this.distributionClient.start();\r
-        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {\r
-            logger.error("SDC distribution client start failed with reason:" + result.getDistributionMessageResult());\r
-            this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);\r
-            throw new SdcControllerException(\r
-                    "Startup of the SDC Controller failed with reason: " + result.getDistributionMessageResult());\r
-        }\r
-        this.changeControllerStatus(SdcSingleControllerStatus.IDLE);\r
-    }\r
-\r
-    /**\r
-     * This method closes the SDC Controller and the SDC Client.\r
-     *\r
-     * @throws SdcControllerException\r
-     *             It throws an exception if the SDC Client cannot be closed\r
-     *             because it's currently BUSY in processing notifications.\r
-     */\r
-    public void closeSdc() throws SdcControllerException {\r
-        if (this.getControllerStatus() == SdcSingleControllerStatus.BUSY) {\r
-            throw new SdcControllerException("Cannot close the SDC controller as it's currently in BUSY state");\r
-        }\r
-        if (this.distributionClient != null) {\r
-            this.distributionClient.stop();\r
-            // If auto managed we can set it to Null, SdcController controls it.\r
-            // In the other case the client of this class has specified it, so\r
-            // we can't reset it\r
-            if (isSdcClientAutoManaged) {\r
-                // Next init will initialize it with a new SDC Client\r
-                this.distributionClient = null;\r
-            }\r
-        }\r
-        this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);\r
-    }\r
-\r
-    /**\r
-     * This method processes the notification received from Sdc.\r
-     * \r
-     * @param iNotif\r
-     *            The INotificationData\r
-     */\r
-    public void treatNotification(INotificationData iNotif) {\r
-        CsarHandler csar = null;\r
-        try {\r
-            // wait for a random time, so that 2 running Clamp will not treat\r
-            // the same Notification at the same time\r
-            long i = ThreadLocalRandom.current().nextInt(1, 5);\r
-            Thread.sleep(i * 1000L);\r
-            logger.info("Notification received for service UUID:" + iNotif.getServiceUUID());\r
-            this.changeControllerStatus(SdcSingleControllerStatus.BUSY);\r
-            csar = new CsarHandler(iNotif, this.sdcConfig.getSdcControllerName(),\r
-                    refProp.getStringValue(CONFIG_SDC_FOLDER));\r
-            csar.save(downloadTheArtifact(csar.getArtifactElement()));\r
-            if (csarInstaller.isCsarAlreadyDeployed(csar)) {\r
-                this.sendSdcNotification(NotificationType.DOWNLOAD, csar.getArtifactElement().getArtifactURL(),\r
-                        sdcConfig.getConsumerID(), iNotif.getDistributionID(),\r
-                        DistributionStatusEnum.ALREADY_DOWNLOADED, null, System.currentTimeMillis());\r
-                this.sendSdcNotification(NotificationType.DOWNLOAD, csar.getArtifactElement().getArtifactURL(),\r
-                        sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.ALREADY_DEPLOYED,\r
-                        null, System.currentTimeMillis());\r
-            } else {\r
-                this.sendSdcNotification(NotificationType.DOWNLOAD, csar.getArtifactElement().getArtifactURL(),\r
-                        sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DOWNLOAD_OK, null,\r
-                        System.currentTimeMillis());\r
-                csarInstaller.installTheCsar(csar);\r
-                this.sendSdcNotification(NotificationType.DEPLOY, csar.getArtifactElement().getArtifactURL(),\r
-                        sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DEPLOY_OK, null,\r
-                        System.currentTimeMillis());\r
-            }\r
-        } catch (SdcArtifactInstallerException e) {\r
-            logger.error("SdcArtifactInstallerException exception caught during the notification processing", e);\r
-            this.sendSdcNotification(NotificationType.DEPLOY, csar.getArtifactElement().getArtifactURL(),\r
-                    sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DEPLOY_ERROR,\r
-                    e.getMessage(), System.currentTimeMillis());\r
-        } catch (SdcDownloadException e) {\r
-            logger.error("SdcDownloadException exception caught during the notification processing", e);\r
-            this.sendSdcNotification(NotificationType.DOWNLOAD, csar.getArtifactElement().getArtifactURL(),\r
-                    sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DOWNLOAD_ERROR,\r
-                    e.getMessage(), System.currentTimeMillis());\r
-        } catch (CsarHandlerException e) {\r
-            logger.error("CsarHandlerException exception caught during the notification processing", e);\r
-            this.sendSdcNotification(NotificationType.DOWNLOAD, null, sdcConfig.getConsumerID(),\r
-                    iNotif.getDistributionID(), DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage(),\r
-                    System.currentTimeMillis());\r
-        } catch (SdcToscaParserException e) {\r
-            logger.error("SdcToscaParserException exception caught during the notification processing", e);\r
-            this.sendSdcNotification(NotificationType.DEPLOY, csar.getArtifactElement().getArtifactURL(),\r
-                    sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DEPLOY_ERROR,\r
-                    e.getMessage(), System.currentTimeMillis());\r
-        } catch (InterruptedException e) {\r
-            logger.error("Interrupt exception caught during the notification processing", e);\r
-            Thread.currentThread().interrupt();\r
-        } catch (RuntimeException e) {\r
-            logger.error("Unexpected exception caught during the notification processing", e);\r
-        } finally {\r
-            this.changeControllerStatus(SdcSingleControllerStatus.IDLE);\r
-        }\r
-    }\r
-\r
-    private enum NotificationType {\r
-        DOWNLOAD, DEPLOY\r
-    }\r
-\r
-    private IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact) throws SdcDownloadException {\r
-        logger.info("Trying to download the artifact : " + artifact.getArtifactURL() + " UUID: "\r
-                + artifact.getArtifactUUID());\r
-        IDistributionClientDownloadResult downloadResult;\r
-        try {\r
-            downloadResult = distributionClient.download(artifact);\r
-            if (null == downloadResult) {\r
-                logger.info("downloadResult is Null for: " + artifact.getArtifactUUID());\r
-                return null;\r
-            }\r
-        } catch (RuntimeException e) {\r
-            throw new SdcDownloadException("Exception caught when downloading the artifact", e);\r
-        }\r
-        if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {\r
-            logger.info("Successfully downloaded the artifact " + artifact.getArtifactURL() + " UUID "\r
-                    + artifact.getArtifactUUID() + "Size of payload " + downloadResult.getArtifactPayload().length);\r
-        } else {\r
-            throw new SdcDownloadException("Artifact " + artifact.getArtifactName()\r
-                    + " could not be downloaded from SDC URL " + artifact.getArtifactURL() + " UUID "\r
-                    + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "\r
-                    + downloadResult.getDistributionMessageResult() + System.lineSeparator());\r
-        }\r
-        return downloadResult;\r
-    }\r
-\r
-    private void sendSdcNotification(NotificationType notificationType, String artifactURL, String consumerID,\r
-            String distributionID, DistributionStatusEnum status, String errorReason, long timestamp) {\r
-        String event = "Sending " + notificationType.name() + "(" + status.name() + ")"\r
-                + " notification to SDC for artifact:" + artifactURL;\r
-        if (errorReason != null) {\r
-            event = event + "(" + errorReason + ")";\r
-        }\r
-        logger.info(event);\r
-        String action = "";\r
-        try {\r
-            IDistributionStatusMessage message = new DistributionStatusMessage(artifactURL, consumerID, distributionID,\r
-                    status, timestamp);\r
-            switch (notificationType) {\r
-                case DOWNLOAD:\r
-                    this.sendDownloadStatus(message, errorReason);\r
-                    action = "sendDownloadStatus";\r
-                    break;\r
-                case DEPLOY:\r
-                    this.sendDeploymentStatus(message, errorReason);\r
-                    action = "sendDeploymentdStatus";\r
-                    break;\r
-                default:\r
-                    break;\r
-            }\r
-        } catch (RuntimeException e) {\r
-            logger.warn("Unable to send the SDC Notification (" + action + ") due to an exception", e);\r
-        }\r
-        logger.info("SDC Notification sent successfully(" + action + ")");\r
-    }\r
-\r
-    private void sendDownloadStatus(IDistributionStatusMessage message, String errorReason) {\r
-        if (errorReason != null) {\r
-            this.distributionClient.sendDownloadStatus(message, errorReason);\r
-        } else {\r
-            this.distributionClient.sendDownloadStatus(message);\r
-        }\r
-    }\r
-\r
-    private void sendDeploymentStatus(IDistributionStatusMessage message, String errorReason) {\r
-        if (errorReason != null) {\r
-            this.distributionClient.sendDeploymentStatus(message, errorReason);\r
-        } else {\r
-            this.distributionClient.sendDeploymentStatus(message);\r
-        }\r
-    }\r
-}\r
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018-2019 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============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.sdc.controller;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.util.Date;
+import java.util.Map.Entry;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.config.sdc.SdcSingleControllerConfiguration;
+import org.onap.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcDownloadException;
+import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact;
+import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.clamp.clds.util.LoggingUtils;
+import org.onap.clamp.loop.CsarInstaller;
+import org.onap.sdc.api.IDistributionClient;
+import org.onap.sdc.api.consumer.IComponentDoneStatusMessage;
+import org.onap.sdc.api.consumer.IDistributionStatusMessage;
+import org.onap.sdc.api.consumer.INotificationCallback;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.api.results.IDistributionClientResult;
+import org.onap.sdc.impl.DistributionClientFactory;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+import org.onap.sdc.utils.DistributionActionResultEnum;
+import org.onap.sdc.utils.DistributionStatusEnum;
+
+/**
+ * This class handles one sdc controller defined in the config.
+ */
+public class SdcSingleController {
+
+    private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcSingleController.class);
+    private boolean isSdcClientAutoManaged = false;
+    private CsarInstaller csarInstaller;
+    private ClampProperties refProp;
+    /**
+     * The constant CONFIG_SDC_FOLDER.
+     */
+    public static final String CONFIG_SDC_FOLDER = "sdc.csarFolder";
+    private int nbOfNotificationsOngoing = 0;
+    private SdcSingleControllerStatus controllerStatus = SdcSingleControllerStatus.STOPPED;
+    private SdcSingleControllerConfiguration sdcConfig;
+    private IDistributionClient distributionClient;
+
+    /**
+     * Inner class for Notification callback.
+     */
+    private final class SdcNotificationCallBack implements INotificationCallback {
+
+        private SdcSingleController sdcController;
+
+        /**
+         * Instantiates a new Sdc notification call back.
+         *
+         * @param controller the controller
+         */
+        SdcNotificationCallBack(SdcSingleController controller) {
+            sdcController = controller;
+        }
+
+        /**
+         * This method can be called multiple times at the same moment. The controller
+         * must be thread safe !
+         */
+        @Override
+        public void activateCallback(INotificationData notificationData) {
+            Date startTime = new Date();
+            logger.info("Receive a callback notification in SDC, nb of resources: "
+                    + notificationData.getResources().size());
+            sdcController.treatNotification(notificationData);
+            LoggingUtils.setTimeContext(startTime, new Date());
+            LoggingUtils.setResponseContext("0", "SDC Notification received and processed successfully",
+                    this.getClass().getName());
+        }
+    }
+
+    /**
+     * Gets nb of notifications ongoing.
+     *
+     * @return the nb of notifications ongoing
+     */
+    public int getNbOfNotificationsOngoing() {
+        return nbOfNotificationsOngoing;
+    }
+
+    private void changeControllerStatusIdle() {
+        if (this.nbOfNotificationsOngoing > 1) {
+            --this.nbOfNotificationsOngoing;
+        } else {
+            this.nbOfNotificationsOngoing = 0;
+            this.controllerStatus = SdcSingleControllerStatus.IDLE;
+        }
+    }
+
+    /**
+     * Change controller status.
+     *
+     * @param newControllerStatus the new controller status
+     */
+    protected final synchronized void changeControllerStatus(SdcSingleControllerStatus newControllerStatus) {
+        switch (newControllerStatus) {
+            case BUSY:
+                ++this.nbOfNotificationsOngoing;
+                this.controllerStatus = newControllerStatus;
+                break;
+            case IDLE:
+                this.changeControllerStatusIdle();
+                break;
+            default:
+                this.controllerStatus = newControllerStatus;
+                break;
+        }
+    }
+
+    /**
+     * Gets controller status.
+     *
+     * @return the controller status
+     */
+    public final synchronized SdcSingleControllerStatus getControllerStatus() {
+        return this.controllerStatus;
+    }
+
+    /**
+     * Instantiates a new Sdc single controller.
+     *
+     * @param clampProp          the clamp prop
+     * @param csarInstaller      the csar installer
+     * @param sdcSingleConfig    the sdc single config
+     * @param distributionClient the distribution client
+     */
+    public SdcSingleController(ClampProperties clampProp, CsarInstaller csarInstaller,
+                               SdcSingleControllerConfiguration sdcSingleConfig,
+                               IDistributionClient distributionClient) {
+        this.distributionClient = distributionClient;
+        isSdcClientAutoManaged = (distributionClient == null);
+        this.sdcConfig = sdcSingleConfig;
+        this.refProp = clampProp;
+        this.csarInstaller = csarInstaller;
+    }
+
+    /**
+     * This method initializes the SDC Controller and the SDC Client.
+     *
+     * @throws SdcControllerException It throws an exception if the SDC Client
+     *                                cannot be instantiated or if an init attempt
+     *                                is done when already initialized
+     */
+    public void initSdc() throws SdcControllerException {
+        logger.info("Attempt to initialize the SDC Controller: " + sdcConfig.getSdcControllerName());
+        if (this.getControllerStatus() != SdcSingleControllerStatus.STOPPED) {
+            throw new SdcControllerException("The controller is already initialized, call the closeSDC method first");
+        }
+        if (distributionClient == null) {
+            distributionClient = DistributionClientFactory.createDistributionClient();
+        }
+        IDistributionClientResult result = distributionClient.init(sdcConfig, new SdcNotificationCallBack(this));
+        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+            logger.error("SDC distribution client init failed with reason:" + result.getDistributionMessageResult());
+            this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+            throw new SdcControllerException("Initialization of the SDC Controller failed with reason: "
+                    + result.getDistributionMessageResult());
+        }
+        logger.info("SDC Controller successfully initialized: " + sdcConfig.getSdcControllerName());
+        logger.info("Attempt to start the SDC Controller: " + sdcConfig.getSdcControllerName());
+        result = this.distributionClient.start();
+        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+            logger.error("SDC distribution client start failed with reason:" + result.getDistributionMessageResult());
+            this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+            throw new SdcControllerException(
+                    "Startup of the SDC Controller failed with reason: " + result.getDistributionMessageResult());
+        }
+        logger.info("SDC Controller successfully started: " + sdcConfig.getSdcControllerName());
+        this.changeControllerStatus(SdcSingleControllerStatus.IDLE);
+    }
+
+    /**
+     * This method closes the SDC Controller and the SDC Client.
+     *
+     * @throws SdcControllerException It throws an exception if the SDC Client
+     *                                cannot be closed because it's currently BUSY
+     *                                in processing notifications.
+     */
+    public void closeSdc() throws SdcControllerException {
+        if (this.getControllerStatus() == SdcSingleControllerStatus.BUSY) {
+            throw new SdcControllerException("Cannot close the SDC controller as it's currently in BUSY state");
+        }
+        if (this.distributionClient != null) {
+            this.distributionClient.stop();
+            // If auto managed we can set it to Null, SdcController controls it.
+            // In the other case the client of this class has specified it, so
+            // we can't reset it
+            if (isSdcClientAutoManaged) {
+                // Next init will initialize it with a new SDC Client
+                this.distributionClient = null;
+            }
+        }
+        this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+    }
+
+    private void sendAllNotificationForCsarHandler(INotificationData notificationData, CsarHandler csar,
+                                                   NotificationType notificationType,
+                                                   DistributionStatusEnum distributionStatus, String errorMessage) {
+        if (csar != null) {
+            // Notify for the CSAR
+            this.sendSdcNotification(notificationType, csar.getArtifactElement().getArtifactURL(),
+                    sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus, errorMessage,
+                    System.currentTimeMillis());
+            // Notify for all VF resources found
+            for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
+                // Normally always 1 artifact in resource for Clamp as we
+                // specified
+                // only VF_METADATA type
+                this.sendSdcNotification(notificationType,
+                        blueprint.getValue().getResourceAttached().getArtifacts().get(0).getArtifactURL(),
+                        sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus,
+                        errorMessage, System.currentTimeMillis());
+            }
+        } else {
+            this.sendSdcNotification(notificationType, null, sdcConfig.getConsumerID(),
+                    notificationData.getDistributionID(), distributionStatus, errorMessage, System.currentTimeMillis());
+        }
+    }
+
+    /**
+     * This method processes the notification received from Sdc.
+     *
+     * @param notificationData The INotificationData
+     */
+    public void treatNotification(INotificationData notificationData) {
+        CsarHandler csar = null;
+        try {
+            // wait for a random time, so that 2 running Clamp will not treat
+            // the same Notification at the same time
+            Thread.sleep(ThreadLocalRandom.current().nextInt(1, 10) * 1000L);
+            logger.info("Notification received for service UUID:" + notificationData.getServiceUUID());
+            this.changeControllerStatus(SdcSingleControllerStatus.BUSY);
+            csar = new CsarHandler(notificationData, this.sdcConfig.getSdcControllerName(),
+                    refProp.getStringValue(CONFIG_SDC_FOLDER));
+            csar.save(downloadTheArtifact(csar.getArtifactElement()));
+            if (csarInstaller.isCsarAlreadyDeployed(csar)) {
+                sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+                        DistributionStatusEnum.ALREADY_DOWNLOADED, null);
+                sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                        DistributionStatusEnum.ALREADY_DEPLOYED, null);
+            } else {
+                sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+                        DistributionStatusEnum.DOWNLOAD_OK, null);
+                csarInstaller.installTheCsar(csar);
+                sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                        DistributionStatusEnum.DEPLOY_OK, null);
+                this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_OK, null);
+            }
+        } catch (SdcArtifactInstallerException | SdcToscaParserException e) {
+            logger.error("SdcArtifactInstallerException exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                    DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+            this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+        } catch (SdcDownloadException | CsarHandlerException e) {
+            logger.error("SdcDownloadException exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+                    DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage());
+            this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+        } catch (InterruptedException e) {
+            logger.error("Interrupt exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                    DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+            this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+            Thread.currentThread().interrupt();
+        } catch (BlueprintParserException e) {
+            logger.error("BlueprintParser exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                    DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+            this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+        } catch (RuntimeException e) {
+            logger.error("Unexpected exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                    DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+            this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+        } finally {
+            this.changeControllerStatus(SdcSingleControllerStatus.IDLE);
+        }
+    }
+
+    private enum NotificationType {
+        /**
+         * Download notification type.
+         */
+        DOWNLOAD,
+        /**
+         * Deploy notification type.
+         */
+        DEPLOY
+    }
+
+    private IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact) throws SdcDownloadException {
+        logger.info("Trying to download the artifact : " + artifact.getArtifactURL() + " UUID: "
+                + artifact.getArtifactUUID());
+        IDistributionClientDownloadResult downloadResult;
+        try {
+            downloadResult = distributionClient.download(artifact);
+            if (null == downloadResult) {
+                logger.info("downloadResult is Null for: " + artifact.getArtifactUUID());
+                return null;
+            }
+        } catch (RuntimeException e) {
+            throw new SdcDownloadException("Exception caught when downloading the artifact", e);
+        }
+        if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
+            logger.info("Successfully downloaded the artifact " + artifact.getArtifactURL() + " UUID "
+                    + artifact.getArtifactUUID() + "Size of payload " + downloadResult.getArtifactPayload().length);
+        } else {
+            throw new SdcDownloadException("Artifact " + artifact.getArtifactName()
+                    + " could not be downloaded from SDC URL " + artifact.getArtifactURL() + " UUID "
+                    + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "
+                    + downloadResult.getDistributionMessageResult() + System.lineSeparator());
+        }
+        return downloadResult;
+    }
+
+    private void sendSdcNotification(NotificationType notificationType, String artifactUrl, String consumerId,
+                                     String distributionId, DistributionStatusEnum status, String errorReason,
+                                     long timestamp) {
+        String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
+                + " notification to SDC for artifact:" + artifactUrl;
+        if (errorReason != null) {
+            event = event + "(" + errorReason + ")";
+        }
+        logger.info(event);
+        String action = "";
+        try {
+            IDistributionStatusMessage message = new DistributionStatusMessage(artifactUrl, consumerId, distributionId,
+                    status, timestamp);
+            switch (notificationType) {
+                case DOWNLOAD:
+                    this.sendDownloadStatus(message, errorReason);
+                    action = "sendDownloadStatus";
+                    break;
+                case DEPLOY:
+                    this.sendDeploymentStatus(message, errorReason);
+                    action = "sendDeploymentdStatus";
+                    break;
+                default:
+                    break;
+            }
+        } catch (RuntimeException e) {
+            logger.warn("Unable to send the SDC Notification (" + action + ") due to an exception", e);
+        }
+        logger.info("SDC Notification sent successfully(" + action + ")");
+    }
+
+    private void sendComponentStatus(INotificationData notificationData, DistributionStatusEnum status,
+                                     String errorReason) {
+        try {
+            IComponentDoneStatusMessage message = new IComponentDoneStatusMessage() {
+
+                @Override public String getDistributionID() {
+                    return notificationData.getDistributionID();
+                }
+
+                @Override public String getConsumerID() {
+                    return sdcConfig.getConsumerID();
+                }
+
+                @Override public long getTimestamp() {
+                    return System.currentTimeMillis();
+                }
+
+                @Override public DistributionStatusEnum getStatus() {
+                    return status;
+                }
+
+                @Override public String getComponentName() {
+                    return sdcConfig.getUser();
+                }
+            };
+
+            if (errorReason != null) {
+                this.distributionClient.sendComponentDoneStatus(message, errorReason);
+            } else {
+                this.distributionClient.sendComponentDoneStatus(message);
+            }
+        } catch (RuntimeException e) {
+            logger.warn("Unable to send the SDC Notification (" + status.name() + ") due to an exception", e);
+        }
+        logger.info("SDC Notification sent successfully(" + status.name() + ")");
+    }
+
+    private void sendDownloadStatus(IDistributionStatusMessage message, String errorReason) {
+        if (errorReason != null) {
+            this.distributionClient.sendDownloadStatus(message, errorReason);
+        } else {
+            this.distributionClient.sendDownloadStatus(message);
+        }
+    }
+
+    private void sendDeploymentStatus(IDistributionStatusMessage message, String errorReason) {
+        if (errorReason != null) {
+            this.distributionClient.sendDeploymentStatus(message, errorReason);
+        } else {
+            this.distributionClient.sendDeploymentStatus(message);
+        }
+    }
+}