Draft single controller 69/36269/1
authorDeterme, Sebastien (sd378r) <sd378r@intl.att.com>
Fri, 16 Mar 2018 18:50:29 +0000 (19:50 +0100)
committerDeterme, Sebastien (sd378r) <sd378r@intl.att.com>
Fri, 16 Mar 2018 18:50:29 +0000 (19:50 +0100)
Draft class that handle one single controller based on the SDC JSon
config

Issue-ID: CLAMP-81
Change-Id: I3db6179c1cb00e21de8b1d58b6e36b49e053fadd
Signed-off-by: Determe, Sebastien (sd378r) <sd378r@intl.att.com>
src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java [new file with mode: 0644]

diff --git a/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java b/src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java
new file mode 100644 (file)
index 0000000..3c87725
--- /dev/null
@@ -0,0 +1,310 @@
+/*-\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
+\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.openecomp.sdc.api.IDistributionClient;\r
+import org.openecomp.sdc.api.consumer.IDistributionStatusMessage;\r
+import org.openecomp.sdc.api.consumer.INotificationCallback;\r
+import org.openecomp.sdc.api.notification.IArtifactInfo;\r
+import org.openecomp.sdc.api.notification.INotificationData;\r
+import org.openecomp.sdc.api.results.IDistributionClientDownloadResult;\r
+import org.openecomp.sdc.api.results.IDistributionClientResult;\r
+import org.openecomp.sdc.impl.DistributionClientFactory;\r
+import org.openecomp.sdc.tosca.parser.exceptions.SdcToscaParserException;\r
+import org.openecomp.sdc.utils.DistributionActionResultEnum;\r
+import org.openecomp.sdc.utils.DistributionStatusEnum;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.stereotype.Component;\r
+\r
+@Component\r
+public class SdcSingleController {\r
+\r
+    private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcSingleController.class);\r
+    protected boolean isAsdcClientAutoManaged = false;\r
+    protected CsarInstaller resourceInstaller;\r
+    @Autowired\r
+    protected ClampProperties refProp;\r
+    public static final String CONFIG_SDC_FOLDER = "sdc.csarFolder";\r
+\r
+    /**\r
+     * Inner class for Notification callback\r
+     */\r
+    private final class ASDCNotificationCallBack implements INotificationCallback {\r
+\r
+        private SdcSingleController asdcController;\r
+\r
+        ASDCNotificationCallBack(SdcSingleController controller) {\r
+            asdcController = 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
+            String event = "Receive a callback notification in ASDC, nb of resources: " + iNotif.getResources().size();\r
+            logger.debug(event);\r
+            asdcController.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
+    // ***** Controller STATUS code\r
+    protected int nbOfNotificationsOngoing = 0;\r
+\r
+    public int getNbOfNotificationsOngoing() {\r
+        return nbOfNotificationsOngoing;\r
+    }\r
+\r
+    private SdcSingleControllerStatus controllerStatus = SdcSingleControllerStatus.STOPPED;\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
+                if (this.nbOfNotificationsOngoing > 1) {\r
+                    --this.nbOfNotificationsOngoing;\r
+                } else {\r
+                    this.nbOfNotificationsOngoing = 0;\r
+                    this.controllerStatus = newControllerStatus;\r
+                }\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
+    // ***** END of Controller STATUS code\r
+    protected SdcSingleControllerConfiguration sdcConfig;\r
+    private IDistributionClient distributionClient;\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.debug("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 ASDCNotificationCallBack(this));\r
+        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {\r
+            logger.error("ASDC 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.debug("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 ASDC 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 (isAsdcClientAutoManaged) {\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
+            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
+            if (resourceInstaller.isCsarAlreadyDeployed(csar)) {\r
+                csar.save(downloadTheArtifact(csar.getArtifactElement()));\r
+                this.sendASDCNotification(NotificationType.DOWNLOAD, csar.getArtifactElement().getArtifactURL(),\r
+                        sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DOWNLOAD_OK, null,\r
+                        System.currentTimeMillis());\r
+                resourceInstaller.installTheCsar(csar);\r
+                this.sendASDCNotification(NotificationType.DEPLOY, csar.getArtifactElement().getArtifactURL(),\r
+                        sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DEPLOY_OK, null,\r
+                        System.currentTimeMillis());\r
+            } else {\r
+                this.sendASDCNotification(NotificationType.DOWNLOAD, csar.getArtifactElement().getArtifactURL(),\r
+                        sdcConfig.getConsumerID(), iNotif.getDistributionID(),\r
+                        DistributionStatusEnum.ALREADY_DOWNLOADED, null, System.currentTimeMillis());\r
+                this.sendASDCNotification(NotificationType.DOWNLOAD, csar.getArtifactElement().getArtifactURL(),\r
+                        sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.ALREADY_DEPLOYED,\r
+                        null, System.currentTimeMillis());\r
+            }\r
+        } catch (SdcArtifactInstallerException e) {\r
+            logger.error("SdcArtifactInstallerException exception caught during the notification processing", e);\r
+            this.sendASDCNotification(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.sendASDCNotification(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.sendASDCNotification(NotificationType.DOWNLOAD, csar.getArtifactElement().getArtifactURL(),\r
+                    sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DOWNLOAD_ERROR,\r
+                    e.getMessage(), System.currentTimeMillis());\r
+        } catch (SdcToscaParserException e) {\r
+            this.sendASDCNotification(NotificationType.DEPLOY, csar.getArtifactElement().getArtifactURL(),\r
+                    sdcConfig.getConsumerID(), iNotif.getDistributionID(), DistributionStatusEnum.DEPLOY_ERROR,\r
+                    e.getMessage(), System.currentTimeMillis());\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.debug("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 ASDC 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 sendASDCNotification(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 ASDC 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
+                    if (errorReason != null) {\r
+                        this.distributionClient.sendDownloadStatus(message, errorReason);\r
+                    } else {\r
+                        this.distributionClient.sendDownloadStatus(message);\r
+                    }\r
+                    action = "sendDownloadStatus";\r
+                    break;\r
+                case DEPLOY:\r
+                    if (errorReason != null) {\r
+                        this.distributionClient.sendDeploymentStatus(message, errorReason);\r
+                    } else {\r
+                        this.distributionClient.sendDeploymentStatus(message);\r
+                    }\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