d1aac97048c036788c6740bbc689383ff3b84886
[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 package org.onap.ccsdk.cds.sdclistener.service;
17
18 import static org.onap.sdc.utils.DistributionStatusEnum.COMPONENT_DONE_ERROR;
19 import static org.onap.sdc.utils.DistributionStatusEnum.COMPONENT_DONE_OK;
20 import com.google.protobuf.ByteString;
21 import io.grpc.ManagedChannel;
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.util.Enumeration;
31 import java.util.List;
32 import java.util.Optional;
33 import java.util.regex.Pattern;
34 import java.util.zip.ZipEntry;
35 import java.util.zip.ZipFile;
36 import org.apache.commons.io.FileUtils;
37 import org.apache.tomcat.util.http.fileupload.IOUtils;
38 import org.onap.ccsdk.cds.controllerblueprints.common.api.Status;
39 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput;
40 import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk;
41 import org.onap.ccsdk.cds.sdclistener.client.SdcListenerAuthClientInterceptor;
42 import org.onap.ccsdk.cds.sdclistener.dto.SdcListenerDto;
43 import org.onap.ccsdk.cds.sdclistener.handler.BluePrintProcesssorHandler;
44 import org.onap.ccsdk.cds.sdclistener.status.SdcListenerStatus;
45 import org.onap.ccsdk.cds.sdclistener.util.FileUtil;
46 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.springframework.beans.factory.annotation.Autowired;
50 import org.springframework.beans.factory.annotation.Value;
51 import org.springframework.boot.context.properties.ConfigurationProperties;
52 import org.springframework.stereotype.Component;
53
54 @Component
55 @ConfigurationProperties("listenerservice")
56 public class ListenerServiceImpl implements ListenerService {
57
58     @Autowired
59     private BluePrintProcesssorHandler bluePrintProcesssorHandler;
60
61     @Autowired
62     private SdcListenerAuthClientInterceptor sdcListenerAuthClientInterceptor;
63
64     @Autowired
65     private SdcListenerStatus listenerStatus;
66
67     @Autowired
68     private SdcListenerDto sdcListenerDto;
69
70     @Value("${listenerservice.config.grpcAddress}")
71     private String grpcAddress;
72
73     @Value("${listenerservice.config.grpcPort}")
74     private int grpcPort;
75
76     private static final String CBA_ZIP_PATH = "Artifacts/[a-zA-Z0-9-_.]+/Deployment/CONTROLLER_BLUEPRINT_ARCHIVE/[a-zA-Z0-9-_.()]+[.]zip";
77     private static final int SUCCESS_CODE = 200;
78     private static final Logger LOGGER = LoggerFactory.getLogger(ListenerServiceImpl.class);
79
80     @Override
81     public void extractBluePrint(String csarArchivePath, String cbaArchivePath) {
82         int validPathCount = 0;
83         final String distributionId = sdcListenerDto.getDistributionId();
84         Path cbaStorageDir = getStorageDirectory(cbaArchivePath);
85         try (ZipFile zipFile = new ZipFile(csarArchivePath)) {
86             Enumeration<? extends ZipEntry> entries = zipFile.entries();
87             while (entries.hasMoreElements()) {
88                 ZipEntry entry = entries.nextElement();
89                 String fileName = entry.getName();
90                 if (Pattern.matches(CBA_ZIP_PATH, fileName)) {
91                     validPathCount++;
92                     final String cbaArchiveName = Paths.get(fileName).getFileName().toString();
93                     LOGGER.info("Storing the CBA archive {}", cbaArchiveName);
94                     storeBluePrint(zipFile, cbaArchiveName, cbaStorageDir, entry);
95                 }
96             }
97
98             if (validPathCount == 0) {
99                 final String errorMessage = String
100                     .format("The CBA Archive doesn't exist as per this given regex %s", CBA_ZIP_PATH);
101                 listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_ERROR, errorMessage);
102                 LOGGER.error(errorMessage);
103             }
104
105         } catch (Exception e) {
106             final String errorMessage = String.format("Failed to extract blueprint %s", e.getMessage());
107             listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_ERROR, errorMessage);
108             LOGGER.error(errorMessage);
109         }
110     }
111
112     private void storeBluePrint(ZipFile zipFile, String fileName, Path cbaArchivePath, ZipEntry entry) {
113         Path targetLocation = cbaArchivePath.resolve(fileName);
114         LOGGER.info("The target location for zip file is {}", targetLocation);
115         File targetZipFile = new File(targetLocation.toString());
116
117         try {
118             targetZipFile.createNewFile();
119         } catch (IOException e) {
120             LOGGER.error("Could not able to create file {}", targetZipFile, e);
121         }
122
123         try (InputStream inputStream = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(
124             targetZipFile)) {
125             IOUtils.copy(inputStream, out);
126             LOGGER.info("Successfully store the CBA archive {} at this location", targetZipFile);
127         } catch (Exception e) {
128             LOGGER.error("Failed to put zip file into target location {}, {}", targetLocation, e);
129         }
130     }
131
132     @Override
133     public void saveBluePrintToCdsDatabase(Path cbaArchivePath, ManagedChannel channel) {
134         List<File> zipFiles = FileUtil.getFilesFromDisk(cbaArchivePath);
135         if (!zipFiles.isEmpty()) {
136             zipFiles.forEach(file -> FileUtil.deleteFile(file, cbaArchivePath.toString()));
137             prepareRequestForCdsBackend(zipFiles, channel, cbaArchivePath.toString());
138         } else {
139             LOGGER.error("Could not able to read CBA archives from this location {}", cbaArchivePath);
140         }
141     }
142
143     @Override
144     public void extractCsarAndStore(IDistributionClientDownloadResult result, Path csarArchivePath) {
145
146         // Create CSAR storage directory
147         Path csarStorageDir = getStorageDirectory(csarArchivePath.toString());
148         byte[] payload = result.getArtifactPayload();
149         String csarFileName = result.getArtifactFilename();
150         Path targetLocation = csarStorageDir.resolve(csarFileName);
151
152         LOGGER.info("The target location for the CSAR file is {}", targetLocation);
153
154         File targetCsarFile = new File(targetLocation.toString());
155
156         try (FileOutputStream outFile = new FileOutputStream(targetCsarFile)) {
157             outFile.write(payload, 0, payload.length);
158             if (!csarArchivePath.toFile().exists()) {
159                 LOGGER.error("Could not able to store the CSAR at this location {}", csarArchivePath);
160             }
161         } catch (Exception e) {
162             LOGGER.error("Fail to write the data into FileOutputStream {}, {}", targetLocation, e);
163         }
164     }
165
166     private Path getStorageDirectory(String path) {
167         Path fileStorageLocation = Paths.get(path).toAbsolutePath().normalize();
168
169         if (!fileStorageLocation.toFile().exists()) {
170             try {
171                 return Files.createDirectories(fileStorageLocation);
172             } catch (IOException e) {
173                 LOGGER.error("Fail to create directory {}, {}", e, fileStorageLocation);
174             }
175         }
176         return fileStorageLocation;
177     }
178
179     private void prepareRequestForCdsBackend(List<File> files, ManagedChannel managedChannel, String path) {
180         final String distributionId = sdcListenerDto.getDistributionId();
181
182         files.forEach(zipFile -> {
183             try {
184                 final BluePrintUploadInput request = generateBluePrintUploadInputBuilder(zipFile);
185
186                 // Send request to CDS Backend.
187                 final Status responseStatus = bluePrintProcesssorHandler.sendRequest(request, managedChannel);
188
189                 if (responseStatus.getCode() != SUCCESS_CODE) {
190                     final String errorMessage = String.format("Failed to store the CBA archive into CDS DB due to %s",
191                         responseStatus.getErrorMessage());
192                     listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_ERROR, errorMessage);
193                     LOGGER.error(errorMessage);
194                 } else {
195                     LOGGER.info(responseStatus.getMessage());
196                     listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_OK, null);
197                 }
198
199             } catch (Exception e) {
200                 final String errorMessage = String.format("Failure due to %s", e.getMessage());
201                 listenerStatus.sendResponseStatusBackToSDC(distributionId, COMPONENT_DONE_ERROR, errorMessage);
202                 LOGGER.error(errorMessage);
203             } finally {
204                 FileUtil.deleteFile(zipFile, path);
205             }
206         });
207     }
208
209     private BluePrintUploadInput generateBluePrintUploadInputBuilder(File file) throws IOException {
210         byte[] bytes = FileUtils.readFileToByteArray(file);
211         FileChunk fileChunk = FileChunk.newBuilder().setChunk(ByteString.copyFrom(bytes)).build();
212
213         return BluePrintUploadInput.newBuilder()
214                 .setFileChunk(fileChunk)
215                 .build();
216     }
217 }