37052082ab962e8c5f2dd8d239f64a5292b1d8c6
[ccsdk/cds.git] /
1 /*
2  * Copyright (C) 2019 Bell Canada. All rights reserved.
3  *
4  * NOTICE:  All the intellectual and technical concepts contained herein are
5  * proprietary to Bell Canada and are protected by trade secret or copyright law.
6  * Unauthorized copying of this file, via any medium is strictly prohibited.
7  */
8
9 package org.onap.ccsdk.cds.cdssdclistener.service;
10
11 import static java.nio.file.Files.walk;
12 import com.google.protobuf.ByteString;
13 import io.grpc.ManagedChannel;
14 import io.grpc.ManagedChannelBuilder;
15 import java.io.File;
16 import java.io.FileOutputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.OutputStream;
20 import java.nio.file.Files;
21 import java.nio.file.Path;
22 import java.nio.file.Paths;
23 import java.util.Enumeration;
24 import java.util.List;
25 import java.util.Optional;
26 import java.util.regex.Pattern;
27 import java.util.stream.Collectors;
28 import java.util.stream.Stream;
29 import java.util.zip.ZipEntry;
30 import java.util.zip.ZipFile;
31 import org.apache.commons.io.FileUtils;
32 import org.apache.tomcat.util.http.fileupload.IOUtils;
33 import org.onap.ccsdk.cds.cdssdclistener.client.CdsSdcListenerAuthClientInterceptor;
34 import org.onap.ccsdk.cds.cdssdclistener.handler.BluePrintProcesssorHandler;
35 import org.onap.ccsdk.cds.controllerblueprints.common.api.Status;
36 import org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintUploadInput;
37 import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk;
38 import org.onap.sdc.api.results.IDistributionClientDownloadResult;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.beans.factory.annotation.Autowired;
42 import org.springframework.beans.factory.annotation.Value;
43 import org.springframework.boot.context.properties.ConfigurationProperties;
44 import org.springframework.stereotype.Component;
45
46 @Component
47 @ConfigurationProperties("listenerservice")
48 public class ListenerServiceImpl implements ListenerService {
49
50     @Autowired
51     private BluePrintProcesssorHandler bluePrintProcesssorHandler;
52
53     @Autowired
54     private CdsSdcListenerAuthClientInterceptor cdsSdcListenerAuthClientInterceptor;
55
56     @Value("${listenerservice.config.grpcAddress}")
57     private String grpcAddress;
58
59     @Value("${listenerservice.config.grpcPort}")
60     private int grpcPort;
61
62     private static final String CBA_ZIP_PATH = "Artifacts/Resources/[a-zA-Z0-9-_]+/Deployment/CONTROLLER_BLUEPRINT_ARCHIVE/[a-zA-Z0-9-_]+[.]zip";
63     private static final int SUCCESS_CODE = 200;
64     private static final String CSAR_FILE_EXTENSION = ".csar";
65     private static final Logger LOGGER = LoggerFactory.getLogger(ListenerServiceImpl.class);
66
67     @Override
68     public void extractBluePrint(String csarArchivePath, String cbaArchivePath) {
69         Path cbaStorageDir = getStorageDirectory(cbaArchivePath);
70         try (ZipFile zipFile = new ZipFile(csarArchivePath)) {
71             Enumeration<? extends ZipEntry> entries = zipFile.entries();
72             while (entries.hasMoreElements()) {
73                 ZipEntry entry = entries.nextElement();
74                 String fileName = entry.getName();
75                 if (Pattern.matches(CBA_ZIP_PATH, fileName)) {
76                     final String cbaArchiveName = Paths.get(fileName).getFileName().toString();
77                     LOGGER.info("Storing the CBA archive {}", cbaArchiveName);
78                     storeBluePrint(zipFile, cbaArchiveName, cbaStorageDir, entry);
79                 }
80             }
81         } catch (Exception e) {
82             LOGGER.error("Failed to extract blueprint", e);
83         }
84     }
85
86     private void storeBluePrint(ZipFile zipFile, String fileName, Path cbaArchivePath, ZipEntry entry) {
87         Path targetLocation = cbaArchivePath.resolve(fileName);
88         LOGGER.info("The target location for zip file is {}", targetLocation);
89         File targetZipFile = new File(targetLocation.toString());
90
91         try {
92             targetZipFile.createNewFile();
93         } catch (IOException e) {
94             LOGGER.error("Could not able to create file {}", targetZipFile, e);
95         }
96
97         try (InputStream inputStream = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(
98             targetZipFile)) {
99             IOUtils.copy(inputStream, out);
100             LOGGER.info("Succesfully store the CBA archive {} at this location", targetZipFile);
101         } catch (Exception e) {
102             LOGGER.error("Failed to put zip file into target location {}, {}", targetLocation, e);
103         }
104     }
105
106     @Override
107     public void saveBluePrintToCdsDatabase(Path cbaArchivePath) {
108         Optional<List<File>> zipFiles = getFilesFromDisk(cbaArchivePath);
109         zipFiles.ifPresent(this::prepareRequestForCdsBackend);
110     }
111
112     @Override
113     public void extractCsarAndStore(IDistributionClientDownloadResult result, String csarArchivePath) {
114
115         // Create CSAR storage directory
116         Path csarStorageDir = getStorageDirectory(csarArchivePath);
117
118         byte[] payload = result.getArtifactPayload();
119         String csarFileName = result.getArtifactFilename() + CSAR_FILE_EXTENSION;
120         Path targetLocation = csarStorageDir.resolve(csarFileName);
121
122         LOGGER.info("The target location for the CSAR file is {}", targetLocation);
123
124         File targetCsarFile = new File(targetLocation.toString());
125
126         try (FileOutputStream outFile = new FileOutputStream(targetCsarFile)) {
127             outFile.write(payload, 0, payload.length);
128         } catch (Exception e) {
129             LOGGER.error("Failed to put CSAR file into target location {}, {}", targetLocation, e);
130         }
131     }
132
133     private Path getStorageDirectory(String path) {
134         Path fileStorageLocation = Paths.get(path).toAbsolutePath().normalize();
135
136         if (!fileStorageLocation.toFile().exists()) {
137             try {
138                 return Files.createDirectories(fileStorageLocation);
139             } catch (IOException e) {
140                 LOGGER.error("Fail to create directory", e);
141             }
142         }
143         return fileStorageLocation;
144     }
145
146     private void prepareRequestForCdsBackend(List<File> files) {
147         final ManagedChannel channel = getManagedChannel();
148
149         files.forEach(zipFile -> {
150             try {
151                 final BluePrintUploadInput request = generateBluePrintUploadInputBuilder(zipFile);
152
153                 // Send request to CDS Backend.
154                 final Status responseStatus = bluePrintProcesssorHandler.sendRequest(request, channel);
155
156                 if (responseStatus.getCode() != SUCCESS_CODE) {
157                     LOGGER.error("Failed to store the CBA archive into CDS DB due to {}",
158                         responseStatus.getErrorMessage());
159                 } else {
160                     LOGGER.info(responseStatus.getMessage());
161                 }
162
163             } catch (Exception e) {
164                 LOGGER.error("Failure due to", e);
165             } finally {
166                 //Delete the file from the local disk.
167                 boolean fileDeleted = zipFile.delete();
168
169                 if (!fileDeleted) {
170                     LOGGER.error("Could not able to delete the zip file {}", zipFile.toString());
171                 }
172             }
173         });
174     }
175
176     private ManagedChannel getManagedChannel() {
177         return ManagedChannelBuilder.forAddress(grpcAddress, grpcPort)
178                                     .usePlaintext()
179                                     .intercept(cdsSdcListenerAuthClientInterceptor)
180                                     .build();
181     }
182
183     private BluePrintUploadInput generateBluePrintUploadInputBuilder(File file) throws IOException {
184         byte[] bytes = FileUtils.readFileToByteArray(file);
185         FileChunk fileChunk = FileChunk.newBuilder().setChunk(ByteString.copyFrom(bytes)).build();
186
187         return BluePrintUploadInput.newBuilder()
188                 .setFileChunk(fileChunk)
189                 .build();
190     }
191
192     /**
193      * Extract files from the given path
194      *
195      * @param path where files reside.
196      * @return list of files.
197      */
198     public Optional<List<File>> getFilesFromDisk(Path path) {
199         try (Stream<Path> fileTree = walk(path)) {
200             // Get the list of files from the path
201             return Optional.of(fileTree.filter(Files::isRegularFile)
202                                        .map(Path::toFile)
203                                        .collect(Collectors.toList()));
204         } catch (IOException e) {
205             LOGGER.error("Failed to find the file", e);
206         }
207
208         return Optional.empty();
209     }
210 }