summaryrefslogtreecommitdiffstats
path: root/artifactbroker/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'artifactbroker/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java')
-rw-r--r--artifactbroker/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java382
1 files changed, 382 insertions, 0 deletions
diff --git a/artifactbroker/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java b/artifactbroker/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java
new file mode 100644
index 0000000..0d100f8
--- /dev/null
+++ b/artifactbroker/plugins/reception-plugins/src/main/java/org/onap/policy/distribution/reception/handling/sdc/SdcReceptionHandler.java
@@ -0,0 +1,382 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2018 Ericsson. 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.distribution.reception.handling.sdc;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.onap.policy.common.logging.flexlogger.FlexLogger;
+import org.onap.policy.common.logging.flexlogger.Logger;
+import org.onap.policy.common.parameters.ParameterService;
+import org.onap.policy.distribution.model.Csar;
+import org.onap.policy.distribution.reception.decoding.PolicyDecodingException;
+import org.onap.policy.distribution.reception.handling.AbstractReceptionHandler;
+import org.onap.policy.distribution.reception.handling.sdc.SdcClientHandler.SdcClientOperationType;
+import org.onap.policy.distribution.reception.handling.sdc.exceptions.ArtifactDownloadException;
+import org.onap.policy.distribution.reception.statistics.DistributionStatisticsManager;
+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.utils.DistributionActionResultEnum;
+import org.onap.sdc.utils.DistributionStatusEnum;
+
+/**
+ * Handles reception of inputs from ONAP Service Design and Creation (SDC) from which policies may be decoded.
+ */
+public class SdcReceptionHandler extends AbstractReceptionHandler implements INotificationCallback {
+
+ private static final Logger LOGGER = FlexLogger.getLogger(SdcReceptionHandler.class);
+ private static final String SECONDS = "Seconds";
+
+ private SdcReceptionHandlerStatus sdcReceptionHandlerStatus = SdcReceptionHandlerStatus.STOPPED;
+ private IDistributionClient distributionClient;
+ private SdcConfiguration sdcConfig;
+ private volatile int nbOfNotificationsOngoing = 0;
+ private int retryDelay;
+ private SdcClientHandler sdcClientHandler;
+
+ private enum DistributionStatusType {
+ DOWNLOAD, DEPLOY
+ }
+
+ @Override
+ protected void initializeReception(final String parameterGroupName) {
+ final SdcReceptionHandlerConfigurationParameterGroup handlerParameters =
+ ParameterService.get(parameterGroupName);
+ retryDelay = handlerParameters.getRetryDelay() < 30 ? 30 : handlerParameters.getRetryDelay();
+ sdcConfig = new SdcConfiguration(handlerParameters);
+ distributionClient = createSdcDistributionClient();
+ sdcClientHandler = new SdcClientHandler(this, SdcClientOperationType.START, retryDelay);
+ }
+
+ @Override
+ public void destroy() {
+ if (distributionClient != null) {
+ sdcClientHandler = new SdcClientHandler(this, SdcClientOperationType.STOP, retryDelay);
+ }
+ }
+
+ @Override
+ public void activateCallback(final INotificationData notificationData) {
+ LOGGER.debug("Receieved the notification from SDC with ID: " + notificationData.getDistributionID());
+ changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.BUSY);
+ processCsarServiceArtifacts(notificationData);
+ changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.IDLE);
+ LOGGER.debug("Processed the notification from SDC with ID: " + notificationData.getDistributionID());
+ }
+
+ /**
+ * Method to change the status of this reception handler instance.
+ *
+ * @param newStatus the new status
+ */
+ private final synchronized void changeSdcReceptionHandlerStatus(final SdcReceptionHandlerStatus newStatus) {
+ switch (newStatus) {
+ case INIT:
+ case STOPPED:
+ sdcReceptionHandlerStatus = newStatus;
+ break;
+ case IDLE:
+ handleIdleStatusChange(newStatus);
+ break;
+ case BUSY:
+ ++nbOfNotificationsOngoing;
+ sdcReceptionHandlerStatus = newStatus;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Creates an instance of {@link IDistributionClient} from {@link DistributionClientFactory}.
+ *
+ * @return the {@link IDistributionClient} instance
+ */
+ protected IDistributionClient createSdcDistributionClient() {
+ return DistributionClientFactory.createDistributionClient();
+ }
+
+ /**
+ * Method to initialize the SDC client.
+ *
+ */
+ protected void initializeSdcClient() {
+
+ LOGGER.debug("Initializing the SDC Client...");
+ if (sdcReceptionHandlerStatus != SdcReceptionHandlerStatus.STOPPED) {
+ LOGGER.error("The SDC Client is already initialized");
+ return;
+ }
+ final IDistributionClientResult clientResult = distributionClient.init(sdcConfig, this);
+ if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ LOGGER.error("SDC client initialization failed with reason:" + clientResult.getDistributionMessageResult()
+ + ". Initialization will be retried after " + retryDelay + SECONDS);
+ return;
+ }
+ LOGGER.debug("SDC Client is initialized successfully");
+ changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.INIT);
+ }
+
+ /**
+ * Method to start the SDC client.
+ *
+ */
+ protected void startSdcClient() {
+
+ LOGGER.debug("Going to start the SDC Client...");
+ if (sdcReceptionHandlerStatus != SdcReceptionHandlerStatus.INIT) {
+ LOGGER.error("The SDC Client is not initialized");
+ return;
+ }
+ final IDistributionClientResult clientResult = distributionClient.start();
+ if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ LOGGER.error("SDC client start failed with reason:" + clientResult.getDistributionMessageResult()
+ + ". Start will be retried after " + retryDelay + SECONDS);
+ return;
+ }
+ LOGGER.debug("SDC Client is started successfully");
+ changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.IDLE);
+ sdcClientHandler.cancel();
+ }
+
+ /**
+ * Method to stop the SDC client.
+ *
+ */
+ protected void stopSdcClient() {
+ LOGGER.debug("Going to stop the SDC Client...");
+ final IDistributionClientResult clientResult = distributionClient.stop();
+ if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ LOGGER.error("SDC client stop failed with reason:" + clientResult.getDistributionMessageResult()
+ + ". Stop will be retried after " + retryDelay + SECONDS);
+ return;
+ }
+ LOGGER.debug("SDC Client is stopped successfully");
+ changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.STOPPED);
+ sdcClientHandler.cancel();
+ }
+
+ /**
+ * Method to process csar service artifacts from incoming SDC notification.
+ *
+ * @param notificationData the notification from SDC
+ */
+ public void processCsarServiceArtifacts(final INotificationData notificationData) {
+ boolean artifactsProcessedSuccessfully = true;
+ DistributionStatisticsManager.updateTotalDistributionCount();
+ for (final IArtifactInfo artifact : notificationData.getServiceArtifacts()) {
+ try {
+ final IDistributionClientDownloadResult resultArtifact =
+ downloadTheArtifact(artifact, notificationData);
+ final Path filePath = writeArtifactToFile(artifact, resultArtifact);
+ final Csar csarObject = new Csar(filePath.toString());
+ inputReceived(csarObject);
+ sendDistributionStatus(DistributionStatusType.DEPLOY, artifact.getArtifactURL(),
+ notificationData.getDistributionID(), DistributionStatusEnum.DEPLOY_OK, null);
+ deleteArtifactFile(filePath);
+ } catch (final ArtifactDownloadException | PolicyDecodingException exp) {
+ LOGGER.error("Failed to process csar service artifacts ", exp);
+ artifactsProcessedSuccessfully = false;
+ sendDistributionStatus(DistributionStatusType.DEPLOY, artifact.getArtifactURL(),
+ notificationData.getDistributionID(), DistributionStatusEnum.DEPLOY_ERROR,
+ "Failed to deploy the artifact due to: " + exp.getMessage());
+ }
+ }
+ if (artifactsProcessedSuccessfully) {
+ DistributionStatisticsManager.updateDistributionSuccessCount();
+ sendComponentDoneStatus(notificationData.getDistributionID(), DistributionStatusEnum.COMPONENT_DONE_OK,
+ null);
+ } else {
+ DistributionStatisticsManager.updateDistributionFailureCount();
+ sendComponentDoneStatus(notificationData.getDistributionID(), DistributionStatusEnum.COMPONENT_DONE_ERROR,
+ "Failed to process the artifact");
+ }
+ }
+
+ /**
+ * Method to download the distribution artifact.
+ *
+ * @param artifact the artifact
+ * @return the download result
+ * @throws ArtifactDownloadException if download fails
+ */
+ private IDistributionClientDownloadResult downloadTheArtifact(final IArtifactInfo artifact,
+ final INotificationData notificationData) throws ArtifactDownloadException {
+
+ DistributionStatisticsManager.updateTotalDownloadCount();
+ final IDistributionClientDownloadResult downloadResult = distributionClient.download(artifact);
+ if (!downloadResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ DistributionStatisticsManager.updateDownloadFailureCount();
+ final String message = "Failed to download artifact with name: " + artifact.getArtifactName() + " due to: "
+ + downloadResult.getDistributionMessageResult();
+ LOGGER.error(message);
+ sendDistributionStatus(DistributionStatusType.DOWNLOAD, artifact.getArtifactURL(),
+ notificationData.getDistributionID(), DistributionStatusEnum.DOWNLOAD_ERROR, message);
+ throw new ArtifactDownloadException(message);
+ }
+ DistributionStatisticsManager.updateDownloadSuccessCount();
+ sendDistributionStatus(DistributionStatusType.DOWNLOAD, artifact.getArtifactURL(),
+ notificationData.getDistributionID(), DistributionStatusEnum.DOWNLOAD_OK, null);
+ return downloadResult;
+ }
+
+ /**
+ * Method to write the downloaded distribution artifact to local file system.
+ *
+ * @param artifact the notification artifact
+ * @param resultArtifact the download result artifact
+ * @return the local path of written file
+ * @throws ArtifactDownloadException if error occurs while writing the artifact
+ */
+ private Path writeArtifactToFile(final IArtifactInfo artifact,
+ final IDistributionClientDownloadResult resultArtifact) throws ArtifactDownloadException {
+ try {
+ final byte[] payloadBytes = resultArtifact.getArtifactPayload();
+ final File tempArtifactFile = File.createTempFile(artifact.getArtifactName(), ".csar");
+ try (FileOutputStream fileOutputStream = new FileOutputStream(tempArtifactFile)) {
+ fileOutputStream.write(payloadBytes, 0, payloadBytes.length);
+ return tempArtifactFile.toPath();
+ }
+ } catch (final Exception exp) {
+ final String message = "Failed to write artifact to local repository";
+ LOGGER.error(message, exp);
+ throw new ArtifactDownloadException(message, exp);
+ }
+ }
+
+ /**
+ * Method to delete the downloaded notification artifact from local file system.
+ *
+ * @param filePath the path of file
+ */
+ private void deleteArtifactFile(final Path filePath) {
+ try {
+ Files.deleteIfExists(filePath);
+ } catch (final IOException exp) {
+ LOGGER.error("Failed to delete the downloaded artifact file", exp);
+ }
+ }
+
+ /**
+ * Sends the distribution status to SDC using the input values.
+ *
+ * @param statusType the status type
+ * @param artifactUrl the artifact url
+ * @param distributionId the distribution id
+ * @param status the status
+ * @param errorReason the error reason
+ */
+ private void sendDistributionStatus(final DistributionStatusType statusType, final String artifactUrl,
+ final String distributionId, final DistributionStatusEnum status, final String errorReason) {
+
+ IDistributionClientResult clientResult;
+ final DistributionStatusMessageBuilder messageBuilder = new DistributionStatusMessageBuilder()
+ .setArtifactUrl(artifactUrl).setConsumerId(sdcConfig.getConsumerID()).setDistributionId(distributionId)
+ .setDistributionStatus(status).setTimestamp(System.currentTimeMillis());
+ final IDistributionStatusMessage message = new DistributionStatusMessage(messageBuilder);
+ if (DistributionStatusType.DOWNLOAD.equals(statusType)) {
+ if (errorReason != null) {
+ clientResult = distributionClient.sendDownloadStatus(message, errorReason);
+ } else {
+ clientResult = distributionClient.sendDownloadStatus(message);
+ }
+ } else {
+ if (errorReason != null) {
+ clientResult = distributionClient.sendDeploymentStatus(message, errorReason);
+ } else {
+ clientResult = distributionClient.sendDeploymentStatus(message);
+ }
+ }
+ final StringBuilder loggerMessage = new StringBuilder();
+ loggerMessage.append("distribution status to SDC with values - ").append("DistributionId")
+ .append(distributionId).append(" Artifact: ").append(artifactUrl).append(" StatusType: ")
+ .append(statusType.name()).append(" Status: ").append(status.name());
+ if (errorReason != null) {
+ loggerMessage.append(" ErrorReason: ").append(errorReason);
+ }
+ if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ loggerMessage.insert(0, "Failed sending ");
+ LOGGER.debug(loggerMessage);
+ } else {
+ loggerMessage.insert(0, "Successfully Sent ");
+ LOGGER.debug(loggerMessage);
+ }
+ }
+
+ /**
+ * Sends the component done status to SDC using the input values.
+ *
+ * @param distributionId the distribution Id
+ * @param status the distribution status
+ * @param errorReason the error reason
+ */
+ private void sendComponentDoneStatus(final String distributionId, final DistributionStatusEnum status,
+ final String errorReason) {
+ IDistributionClientResult clientResult;
+ final ComponentDoneStatusMessageBuilder messageBuilder = new ComponentDoneStatusMessageBuilder()
+ .setConsumerId(sdcConfig.getConsumerID()).setDistributionId(distributionId)
+ .setDistributionStatus(status).setTimestamp(System.currentTimeMillis());
+ final IComponentDoneStatusMessage message = new ComponentDoneStatusMessage(messageBuilder);
+ if (errorReason == null) {
+ clientResult = distributionClient.sendComponentDoneStatus(message);
+ } else {
+ clientResult = distributionClient.sendComponentDoneStatus(message, errorReason);
+ }
+
+ final StringBuilder loggerMessage = new StringBuilder();
+ loggerMessage.append("component done status to SDC with values - ").append("DistributionId")
+ .append(distributionId).append(" Status: ").append(status.name());
+ if (errorReason != null) {
+ loggerMessage.append(" ErrorReason: ").append(errorReason);
+ }
+ if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ loggerMessage.insert(0, "Failed sending ");
+ LOGGER.debug(loggerMessage);
+ } else {
+ loggerMessage.insert(0, "Successfully Sent ");
+ LOGGER.debug(loggerMessage);
+ }
+ }
+
+ /**
+ * Handle the status change of {@link SdcReceptionHandler} to Idle.
+ *
+ * @param newStatus the new status
+ */
+ private void handleIdleStatusChange(final SdcReceptionHandlerStatus newStatus) {
+ if (nbOfNotificationsOngoing > 1) {
+ --nbOfNotificationsOngoing;
+ } else {
+ nbOfNotificationsOngoing = 0;
+ sdcReceptionHandlerStatus = newStatus;
+ }
+ }
+}