f2d8aa4d5dc5e15344233e7b11655c1267843bed
[policy/distribution.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.distribution.reception.handling.sdc;
22
23 import java.io.File;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28
29 import org.onap.policy.common.logging.flexlogger.FlexLogger;
30 import org.onap.policy.common.logging.flexlogger.Logger;
31 import org.onap.policy.common.parameters.ParameterService;
32 import org.onap.policy.distribution.model.Csar;
33 import org.onap.policy.distribution.reception.decoding.PluginInitializationException;
34 import org.onap.policy.distribution.reception.decoding.PluginTerminationException;
35 import org.onap.policy.distribution.reception.decoding.PolicyDecodingException;
36 import org.onap.policy.distribution.reception.handling.AbstractReceptionHandler;
37 import org.onap.policy.distribution.reception.handling.sdc.exceptions.ArtifactDownloadException;
38 import org.onap.sdc.api.IDistributionClient;
39 import org.onap.sdc.api.consumer.INotificationCallback;
40 import org.onap.sdc.api.notification.IArtifactInfo;
41 import org.onap.sdc.api.notification.INotificationData;
42 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
43 import org.onap.sdc.api.results.IDistributionClientResult;
44 import org.onap.sdc.impl.DistributionClientFactory;
45 import org.onap.sdc.utils.DistributionActionResultEnum;
46
47 /**
48  * Handles reception of inputs from ONAP Service Design and Creation (SDC) from which policies may be decoded.
49  */
50 public class SdcReceptionHandler extends AbstractReceptionHandler implements INotificationCallback {
51
52     private static final Logger LOGGER = FlexLogger.getLogger(SdcReceptionHandler.class);
53
54     private SdcReceptionHandlerStatus sdcReceptionHandlerStatus = SdcReceptionHandlerStatus.STOPPED;
55     private SdcReceptionHandlerConfigurationParameterGroup handlerParameters;
56     private IDistributionClient distributionClient;
57     private volatile int nbOfNotificationsOngoing = 0;
58
59     @Override
60     protected void initializeReception(final String parameterGroupName) throws PluginInitializationException {
61         handlerParameters = (SdcReceptionHandlerConfigurationParameterGroup) ParameterService.get(parameterGroupName);
62         initializeSdcClient();
63         startSdcClient();
64     }
65
66     // Add functionality for receiving SDC distibutions and invoking AbstractReceptionHandler
67     // inputReceived()
68
69     @Override
70     public void destroy() throws PluginTerminationException {
71         LOGGER.debug("Going to stop the SDC Client...");
72         if (distributionClient != null) {
73             final IDistributionClientResult clientResult = distributionClient.stop();
74             if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
75                 final String message =
76                         "SDC client stop failed with reason:" + clientResult.getDistributionMessageResult();
77                 LOGGER.error(message);
78                 throw new PluginTerminationException(message);
79             }
80         }
81         changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.STOPPED);
82         LOGGER.debug("SDC Client is stopped successfully");
83     }
84
85     @Override
86     public void activateCallback(final INotificationData notificationData) {
87         LOGGER.debug("Receieved the notification from SDC with ID: " + notificationData.getDistributionID());
88         changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.BUSY);
89         processCsarServiceArtifacts(notificationData);
90         changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.IDLE);
91         LOGGER.debug("Processed the notification from SDC with ID: " + notificationData.getDistributionID());
92     }
93
94     /**
95      * Method to change the status of this reception handler instance.
96      *
97      * @param newStatus the new status
98      */
99     private synchronized final void changeSdcReceptionHandlerStatus(final SdcReceptionHandlerStatus newStatus) {
100         switch (newStatus) {
101             case INIT:
102             case STOPPED:
103                 sdcReceptionHandlerStatus = newStatus;
104                 break;
105             case IDLE:
106                 if (nbOfNotificationsOngoing > 1) {
107                     --nbOfNotificationsOngoing;
108                 } else {
109                     nbOfNotificationsOngoing = 0;
110                     sdcReceptionHandlerStatus = newStatus;
111                 }
112                 break;
113             case BUSY:
114                 ++nbOfNotificationsOngoing;
115                 sdcReceptionHandlerStatus = newStatus;
116                 break;
117         }
118     }
119
120     /**
121      * Creates an instance of {@link IDistributionClient} from {@link DistributionClientFactory}.
122      *
123      * @return the {@link IDistributionClient} instance
124      */
125     protected IDistributionClient createSdcDistributionClient() {
126         return DistributionClientFactory.createDistributionClient();
127     }
128
129     /**
130      * Method to initialize the SDC client.
131      *
132      * @throws PluginInitializationException if the initialization of SDC Client fails
133      */
134     private void initializeSdcClient() throws PluginInitializationException {
135
136         LOGGER.debug("Initializing the SDC Client...");
137         if (sdcReceptionHandlerStatus != SdcReceptionHandlerStatus.STOPPED) {
138             final String message = "The SDC Client is already initialized";
139             LOGGER.error(message);
140             throw new PluginInitializationException(message);
141         }
142         final SdcConfiguration sdcConfig = new SdcConfiguration(handlerParameters);
143         distributionClient = createSdcDistributionClient();
144         final IDistributionClientResult clientResult = distributionClient.init(sdcConfig, this);
145         if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
146             changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.STOPPED);
147             final String message =
148                     "SDC client initialization failed with reason:" + clientResult.getDistributionMessageResult();
149             LOGGER.error(message);
150             throw new PluginInitializationException(message);
151         }
152         LOGGER.debug("SDC Client is initialized successfully");
153         this.changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.INIT);
154     }
155
156     /**
157      * Method to start the SDC client.
158      *
159      * @param configParameter the configuration parameters
160      * @throws PluginInitializationException if the start of SDC Client fails
161      */
162     private void startSdcClient() throws PluginInitializationException {
163
164         LOGGER.debug("Going to start the SDC Client...");
165         final IDistributionClientResult clientResult = distributionClient.start();
166         if (!clientResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
167             changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.STOPPED);
168             final String message = "SDC client start failed with reason:" + clientResult.getDistributionMessageResult();
169             LOGGER.error(message);
170             throw new PluginInitializationException(message);
171         }
172         LOGGER.debug("SDC Client is started successfully");
173         this.changeSdcReceptionHandlerStatus(SdcReceptionHandlerStatus.IDLE);
174     }
175
176     /**
177      * Method to process csar service artifacts from incoming SDC notification.
178      *
179      * @param iNotif the notification from SDC
180      */
181     public void processCsarServiceArtifacts(final INotificationData iNotif) {
182         boolean artifactsProcessedSuccessfully = true;
183
184         for (final IArtifactInfo artifact : iNotif.getServiceArtifacts()) {
185             try {
186                 final IDistributionClientDownloadResult resultArtifact = downloadTheArtifact(artifact);
187                 final Path filePath = writeArtifactToFile(artifact, resultArtifact);
188                 final Csar csarObject = new Csar(filePath.toString());
189                 inputReceived(csarObject);
190                 // send deploy success status to sdc
191                 deleteArtifactFile(filePath);
192             } catch (final ArtifactDownloadException | PolicyDecodingException exp) {
193                 LOGGER.error("Failed to process csar service artifacts ", exp);
194                 artifactsProcessedSuccessfully = false;
195                 // send deploy failed status to sdc
196             }
197         }
198         if (artifactsProcessedSuccessfully) {
199             // send final distribution success status to sdc
200         } else {
201             // send final distribution failed status to sdc
202         }
203     }
204
205     /**
206      * Method to download the distribution artifact.
207      *
208      * @param artifact the artifact
209      * @return the download result
210      * @throws ArtifactDownloadException if download fails
211      */
212     private IDistributionClientDownloadResult downloadTheArtifact(final IArtifactInfo artifact)
213             throws ArtifactDownloadException {
214
215         final IDistributionClientDownloadResult downloadResult = distributionClient.download(artifact);
216         if (!downloadResult.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
217             final String message = "Failed to download artifact with name: " + artifact.getArtifactName();
218             LOGGER.error(message);
219             // send failure download status to sdc
220             throw new ArtifactDownloadException(message);
221         }
222         // send success download status to sdc
223         return downloadResult;
224     }
225
226     /**
227      * Method to write the downloaded distribution artifact to local file system.
228      *
229      * @param artifact the notification artifact
230      * @param resultArtifact the download result artifact
231      * @return the local path of written file
232      * @throws ArtifactDownloadException if error occurs while writing the artifact
233      */
234     private Path writeArtifactToFile(final IArtifactInfo artifact,
235             final IDistributionClientDownloadResult resultArtifact) throws ArtifactDownloadException {
236         try {
237             final byte[] payloadBytes = resultArtifact.getArtifactPayload();
238             final File tempArtifactFile = File.createTempFile(artifact.getArtifactName(), null);
239             try (FileOutputStream fileOutputStream = new FileOutputStream(tempArtifactFile)) {
240                 fileOutputStream.write(payloadBytes, 0, payloadBytes.length);
241                 return tempArtifactFile.toPath();
242             }
243         } catch (final Exception exp) {
244             final String message = "Failed to write artifact to local repository";
245             LOGGER.error(message, exp);
246             throw new ArtifactDownloadException(message, exp);
247         }
248     }
249
250     /**
251      * Method to delete the downloaded notification artifact from local file system.
252      *
253      * @param filePath the path of file
254      */
255     private void deleteArtifactFile(final Path filePath) {
256         try {
257             Files.deleteIfExists(filePath);
258         } catch (final IOException exp) {
259             LOGGER.error("Failed to delete the downloaded artifact file", exp);
260         }
261     }
262 }