19a62fb1d396047a18551ee5d038151b8b1cb7ce
[ccsdk/cds.git] / ms / sdclistener / application / src / main / java / org / onap / ccsdk / cds / sdclistener / service / ListenerServiceImpl.java
1 /*
2  * Copyright © 2019 Bell Canada
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.ccsdk.cds.sdclistener.service;
18
19 import com.google.protobuf.ByteString;
20 import io.grpc.ManagedChannel;
21 import org.apache.commons.io.FileUtils;
22 import org.apache.commons.io.IOUtils;
23 import org.onap.ccsdk.cds.controllerblueprints.common.api.ActionIdentifiers;
24 import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader;
25 import org.onap.ccsdk.cds.controllerblueprints.common.api.Status;
26 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput;
27 import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk;
28 import org.onap.ccsdk.cds.controllerblueprints.management.api.UploadAction;
29 import org.onap.ccsdk.cds.sdclistener.client.SdcListenerAuthClientInterceptor;
30 import org.onap.ccsdk.cds.sdclistener.dto.SdcListenerDto;
31 import org.onap.ccsdk.cds.sdclistener.handler.BluePrintProcesssorHandler;
32 import org.onap.ccsdk.cds.sdclistener.status.SdcListenerStatus;
33 import org.onap.ccsdk.cds.sdclistener.util.FileUtil;
34 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.springframework.beans.factory.annotation.Autowired;
38 import org.springframework.beans.factory.annotation.Value;
39 import org.springframework.boot.context.properties.ConfigurationProperties;
40 import org.springframework.stereotype.Component;
41
42 import java.io.File;
43 import java.io.FileOutputStream;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.OutputStream;
47 import java.nio.file.Files;
48 import java.nio.file.Path;
49 import java.nio.file.Paths;
50 import java.util.Enumeration;
51 import java.util.List;
52 import java.util.UUID;
53 import java.util.regex.Pattern;
54 import java.util.zip.ZipEntry;
55 import java.util.zip.ZipFile;
56
57 import static java.lang.String.format;
58 import static org.onap.ccsdk.cds.sdclistener.status.SdcListenerStatus.NotificationType.SDC_LISTENER_COMPONENT;
59 import static org.onap.sdc.utils.DistributionStatusEnum.COMPONENT_DONE_ERROR;
60 import static org.onap.sdc.utils.DistributionStatusEnum.COMPONENT_DONE_OK;
61
62 @Component
63 @ConfigurationProperties("listenerservice")
64 public class ListenerServiceImpl implements ListenerService {
65
66     @Autowired
67     private BluePrintProcesssorHandler bluePrintProcesssorHandler;
68
69     @Autowired
70     private SdcListenerAuthClientInterceptor sdcListenerAuthClientInterceptor;
71
72     @Autowired
73     private SdcListenerStatus listenerStatus;
74
75     @Autowired
76     private SdcListenerDto sdcListenerDto;
77
78     @Value("${listenerservice.config.grpcAddress}")
79     private String grpcAddress;
80
81     @Value("${listenerservice.config.grpcPort}")
82     private int grpcPort;
83
84     private static final String CBA_ZIP_PATH = "Artifacts/[a-zA-Z0-9-_.]+/Deployment/CONTROLLER_BLUEPRINT_ARCHIVE/[a-zA-Z0-9-_.()]+[.]zip";
85     private static final int SUCCESS_CODE = 200;
86     private static final Logger LOGGER = LoggerFactory.getLogger(ListenerServiceImpl.class);
87
88     @Override
89     public void extractBluePrint(String csarArchivePath, String cbaArchivePath) {
90         int validPathCount = 0;
91         final String distributionId = getDistributionId();
92         final String artifactUrl = getArtifactUrl();
93         Path cbaStorageDir = getStorageDirectory(cbaArchivePath);
94         try (ZipFile zipFile = new ZipFile(csarArchivePath)) {
95             Enumeration<? extends ZipEntry> entries = zipFile.entries();
96             while (entries.hasMoreElements()) {
97                 ZipEntry entry = entries.nextElement();
98                 String fileName = entry.getName();
99                 if (Pattern.matches(CBA_ZIP_PATH, fileName)) {
100                     validPathCount++;
101                     final String cbaArchiveName = Paths.get(fileName).getFileName().toString();
102                     LOGGER.info("Storing the CBA archive {}", cbaArchiveName);
103                     storeBluePrint(zipFile, cbaArchiveName, cbaStorageDir, entry);
104                 }
105             }
106
107             if (validPathCount == 0) {
108                 LOGGER
109                         .info("CBA archive doesn't exist in the CSAR Package or it doesn't exist as per the given path {}",
110                                 CBA_ZIP_PATH);
111                 listenerStatus.sendResponseBackToSdc(distributionId, COMPONENT_DONE_OK, null,
112                         artifactUrl, SDC_LISTENER_COMPONENT);
113             }
114
115         } catch (Exception e) {
116             final String errorMessage = format("Failed to extract blueprint %s", e.getMessage());
117             listenerStatus.sendResponseBackToSdc(distributionId, COMPONENT_DONE_ERROR, errorMessage,
118                     artifactUrl, SDC_LISTENER_COMPONENT);
119             LOGGER.error(errorMessage);
120         }
121     }
122
123     private void storeBluePrint(ZipFile zipFile, String fileName, Path cbaArchivePath, ZipEntry entry) {
124         Path targetLocation = cbaArchivePath.resolve(fileName);
125         LOGGER.info("The target location for zip file is {}", targetLocation);
126         File targetZipFile = new File(targetLocation.toString());
127
128         try {
129             if (!targetZipFile.createNewFile()) {
130                 LOGGER.warn("Overwriting zip file {}", targetLocation);
131             }
132         } catch (IOException e) {
133             LOGGER.error("Could not able to create file {}", targetZipFile, e);
134         }
135
136         try (InputStream inputStream = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(
137                 targetZipFile)) {
138             IOUtils.copy(inputStream, out);
139             LOGGER.info("Successfully store the CBA archive {} at this location", targetZipFile);
140         } catch (Exception e) {
141             LOGGER.error("Failed to put zip file into target location {}, {}", targetLocation, e);
142         }
143     }
144
145     @Override
146     public void saveBluePrintToCdsDatabase(Path cbaArchivePath, ManagedChannel channel) {
147         List<File> zipFiles = FileUtil.getFilesFromDisk(cbaArchivePath);
148         if (!zipFiles.isEmpty()) {
149             prepareRequestForCdsBackend(zipFiles, channel, cbaArchivePath.toString());
150         }
151     }
152
153     @Override
154     public void extractCsarAndStore(IDistributionClientDownloadResult result, Path csarArchivePath) {
155
156         // Create CSAR storage directory
157         Path csarStorageDir = getStorageDirectory(csarArchivePath.toString());
158         byte[] payload = result.getArtifactPayload();
159         String csarFileName = result.getArtifactFilename();
160         Path targetLocation = csarStorageDir.resolve(csarFileName);
161
162         LOGGER.info("The target location for the CSAR file is {}", targetLocation);
163
164         File targetCsarFile = new File(targetLocation.toString());
165
166         try (FileOutputStream outFile = new FileOutputStream(targetCsarFile)) {
167             outFile.write(payload, 0, payload.length);
168             if (!csarArchivePath.toFile().exists()) {
169                 LOGGER.error("Could not able to store the CSAR at this location {}", csarArchivePath);
170             }
171         } catch (Exception e) {
172             LOGGER.error("Fail to write the data into FileOutputStream {}, {}", targetLocation, e);
173         }
174     }
175
176     private Path getStorageDirectory(String path) {
177         Path fileStorageLocation = Paths.get(path).toAbsolutePath().normalize();
178
179         if (!fileStorageLocation.toFile().exists()) {
180             try {
181                 return Files.createDirectories(fileStorageLocation);
182             } catch (IOException e) {
183                 LOGGER.error("Fail to create directory {}, {}", e, fileStorageLocation);
184             }
185         }
186         return fileStorageLocation;
187     }
188
189     private void prepareRequestForCdsBackend(List<File> files, ManagedChannel managedChannel, String path) {
190         final String distributionId = getDistributionId();
191         final String artifactUrl = getArtifactUrl();
192
193         files.forEach(zipFile -> {
194             try {
195                 final BluePrintUploadInput request = generateBluePrintUploadInputBuilder(zipFile, path);
196
197                 // Send request to CDS Backend.
198                 final Status responseStatus = bluePrintProcesssorHandler.sendRequest(request, managedChannel);
199
200                 if (responseStatus.getCode() != SUCCESS_CODE) {
201                     final String errorMessage = format("Failed to store the CBA archive into CDS DB due to %s",
202                             responseStatus.getErrorMessage());
203                     listenerStatus.sendResponseBackToSdc(distributionId, COMPONENT_DONE_ERROR, errorMessage, artifactUrl,
204                             SDC_LISTENER_COMPONENT);
205                     LOGGER.error(errorMessage);
206                 } else {
207                     LOGGER.info(responseStatus.getMessage());
208                     listenerStatus.sendResponseBackToSdc(distributionId, COMPONENT_DONE_OK, null, artifactUrl,
209                             SDC_LISTENER_COMPONENT);
210                 }
211
212             } catch (Exception e) {
213                 final String errorMessage = format("Failure due to %s", e.getMessage());
214                 listenerStatus.sendResponseBackToSdc(distributionId, COMPONENT_DONE_ERROR, errorMessage, artifactUrl,
215                         SDC_LISTENER_COMPONENT);
216                 LOGGER.error(errorMessage);
217             }
218         });
219     }
220
221     private BluePrintUploadInput generateBluePrintUploadInputBuilder(File file, String path) throws IOException {
222         byte[] bytes = FileUtils.readFileToByteArray(file);
223         FileChunk fileChunk = FileChunk.newBuilder().setChunk(ByteString.copyFrom(bytes)).build();
224         FileUtil.deleteFile(file, path);
225         return BluePrintUploadInput.newBuilder()
226                 .setCommonHeader(CommonHeader.newBuilder()
227                         .setRequestId(UUID.randomUUID().toString())
228                         .setSubRequestId(UUID.randomUUID().toString())
229                         .setOriginatorId("SDC-LISTENER")
230                         .build())
231                 .setActionIdentifiers(ActionIdentifiers.newBuilder()
232                         .setActionName(UploadAction.PUBLISH.toString()).build())
233                 .setFileChunk(fileChunk)
234                 .build();
235     }
236
237     private String getDistributionId() {
238         return sdcListenerDto.getDistributionId();
239     }
240
241     private String getArtifactUrl() {
242         return sdcListenerDto.getArtifactUrl();
243     }
244
245 }