--- /dev/null
+/*-\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