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