Merge "Integrate sdc-tosca parser jar"
[externalapi/nbi.git] / src / main / java / org / onap / nbi / apis / servicecatalog / ToscaInfosProcessor.java
1 /**
2  * Copyright (c) 2018 Orange
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package org.onap.nbi.apis.servicecatalog;
15
16 import com.fasterxml.jackson.databind.ObjectMapper;
17 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileOutputStream;
21 import java.io.IOException;
22 import java.nio.file.Path;
23 import java.sql.Timestamp;
24 import java.util.ArrayList;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.Set;
30 import java.util.zip.ZipEntry;
31 import java.util.zip.ZipInputStream;
32 import org.apache.commons.io.FileUtils;
33 import org.onap.nbi.exceptions.TechnicalException;
34 import org.onap.sdc.tosca.parser.api.ISdcCsarHelper;
35 import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
36 import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory;
37 import org.onap.sdc.toscaparser.api.NodeTemplate;
38 import org.onap.sdc.toscaparser.api.parameters.Input;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.beans.factory.annotation.Autowired;
42 import org.springframework.stereotype.Service;
43 import org.springframework.util.CollectionUtils;
44
45 @Service
46 public class ToscaInfosProcessor {
47
48     @Autowired
49     SdcClient sdcClient;
50
51     final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); // jackson databind
52
53     private static final Logger LOGGER = LoggerFactory.getLogger(ToscaInfosProcessor.class);
54
55     public void buildResponseWithToscaInfos(Map toscaInfosTopologyTemplate,
56             Map serviceCatalogResponse) {
57         if (toscaInfosTopologyTemplate.get("inputs") != null) {
58             ArrayList serviceSpecCharacteristic = new ArrayList();
59             LinkedHashMap toscaInfos = (LinkedHashMap) toscaInfosTopologyTemplate.get("inputs");
60             Set<Entry<String, LinkedHashMap>> stringLinkedHashMapEntry = (Set<Entry<String, LinkedHashMap>>) toscaInfos
61                 .entrySet();
62
63             for (Map.Entry<String,LinkedHashMap> key :stringLinkedHashMapEntry) {
64                 String keyString = key.getKey();
65                 LinkedHashMap inputParameter = key.getValue();
66                 LinkedHashMap mapParameter = new LinkedHashMap();
67                 String parameterType = (String) inputParameter.get("type");
68                 mapParameter.put("name", keyString);
69                 mapParameter.put("description", inputParameter.get("description"));
70                 mapParameter.put("valueType", parameterType);
71                 mapParameter.put("@type", "ONAPserviceCharacteristic");
72                 mapParameter.put("required", inputParameter.get("required"));
73                 mapParameter.put("status", inputParameter.get("status"));
74                 List<LinkedHashMap> serviceSpecCharacteristicValues =
75                     buildServiceSpecCharacteristicsValues(inputParameter, parameterType);
76                 mapParameter.put("serviceSpecCharacteristicValue", serviceSpecCharacteristicValues);
77                 serviceSpecCharacteristic.add(mapParameter);
78             }
79
80             serviceCatalogResponse.put("serviceSpecCharacteristic", serviceSpecCharacteristic);
81         }
82         LinkedHashMap nodeTemplate = (LinkedHashMap) toscaInfosTopologyTemplate.get("node_templates");
83
84         List<LinkedHashMap> resourceSpecifications =
85                 (List<LinkedHashMap>) serviceCatalogResponse.get("resourceSpecification");
86         for (LinkedHashMap resourceSpecification : resourceSpecifications) {
87             if(resourceSpecification.get("id")!=null){
88                 String id = (String) resourceSpecification.get("id");
89                 LOGGER.debug("get tosca infos for service id: {}", id);
90                 LinkedHashMap toscaInfosFromResourceId = getToscaInfosFromResourceUUID(nodeTemplate, id);
91                 if (toscaInfosFromResourceId != null && toscaInfosFromResourceId.get("customizationUUID")!=null) {
92                     resourceSpecification.put("modelCustomizationId", toscaInfosFromResourceId.get("customizationUUID"));
93                 }
94             }
95         }
96     }
97     
98     public void buildResponseWithSdcToscaParser(Path path, Map serviceCatalogResponse) throws SdcToscaParserException {
99
100         SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance();
101         ISdcCsarHelper sdcCsarHelper = factory.getSdcCsarHelper(path.toFile().getAbsolutePath(),false);
102         List<Input> inputs = sdcCsarHelper.getServiceInputs();
103         if(inputs != null && inputs.size() > 0) {
104             ArrayList serviceSpecCharacteristic = new ArrayList();
105             for(Input input : inputs) {
106                     LinkedHashMap mapParameter = new LinkedHashMap();
107                     mapParameter.put("name", input.getName());
108                     mapParameter.put("description", input.getDescription());
109                     mapParameter.put("valueType", input.getType());
110                     mapParameter.put("@type", "ONAPserviceCharacteristic");
111                     mapParameter.put("required", input.isRequired());
112                     mapParameter.put("status", null);
113                     mapParameter.put("serviceSpecCharacteristicValue", null);
114                     // If this Input has a default value, then put it in serviceSpecCharacteristicValue
115                     if (input.getDefault() != null)
116                     {
117                     List<LinkedHashMap> serviceSpecCharacteristicValues =
118                             buildServiceSpecCharacteristicsValuesFromSdc(input);
119                         mapParameter.put("serviceSpecCharacteristicValue", serviceSpecCharacteristicValues);
120                     }
121                     serviceSpecCharacteristic.add(mapParameter);
122             }
123             serviceCatalogResponse.put("serviceSpecCharacteristic", serviceSpecCharacteristic);
124            }
125         List<NodeTemplate> nodeTemplates = sdcCsarHelper.getServiceNodeTemplates();
126
127         List<LinkedHashMap> resourceSpecifications =
128                 (List<LinkedHashMap>) serviceCatalogResponse.get("resourceSpecification");
129         for (LinkedHashMap resourceSpecification : resourceSpecifications) {
130             if(resourceSpecification.get("id")!=null){
131                 String id = (String) resourceSpecification.get("id");
132                 LOGGER.debug("get tosca infos for service id: {}", id);
133                 NodeTemplate nodeTemplate = null;
134                 for(NodeTemplate node : nodeTemplates) {
135                         if(node.getMetaData().getValue("UUID").equals(id)) {
136                                 nodeTemplate = node;
137                                 break;
138                         }
139                 }
140                 if(nodeTemplate == null)
141                         continue;
142                 resourceSpecification.put("modelCustomizationId", sdcCsarHelper.getNodeTemplateCustomizationUuid(nodeTemplate));
143             }
144         }
145     }
146
147         
148     private List<LinkedHashMap> buildServiceSpecCharacteristicsValuesFromSdc(Input input) {
149                 
150         List<LinkedHashMap> serviceSpecCharacteristicValues = new ArrayList<>();
151         LinkedHashMap serviceSpecCharacteristicValue = new LinkedHashMap();
152         
153         serviceSpecCharacteristicValue.put("isDefault", true);
154         serviceSpecCharacteristicValue.put("value", input.getDefault());
155         serviceSpecCharacteristicValue.put("valueType", input.getType());
156         serviceSpecCharacteristicValues.add(serviceSpecCharacteristicValue);
157         
158                 return serviceSpecCharacteristicValues;
159         }
160
161         private List<LinkedHashMap> buildServiceSpecCharacteristicsValues(LinkedHashMap parameter, String parameterType) {
162         List<LinkedHashMap> serviceSpecCharacteristicValues = new ArrayList<>();
163         if (!"map".equalsIgnoreCase(parameterType) && !"list".equalsIgnoreCase(parameterType)) {
164             LOGGER.debug("get tosca infos for serviceSpecCharacteristicValues of type map or string : {}", parameter);
165             Object aDefault = parameter.get("default");
166             if (parameter.get("entry_schema") != null) {
167                 ArrayList entrySchema = (ArrayList) parameter.get("entry_schema");
168                 if (!CollectionUtils.isEmpty(entrySchema)) {
169                     buildCharacteristicValuesFormShema(parameterType, serviceSpecCharacteristicValues, aDefault,
170                             entrySchema);
171                 }
172             }
173         }
174         return serviceSpecCharacteristicValues;
175     }
176
177     private void buildCharacteristicValuesFormShema(String parameterType,
178             List<LinkedHashMap> serviceSpecCharacteristicValues, Object aDefault, ArrayList entrySchema) {
179         LinkedHashMap constraints = (LinkedHashMap) entrySchema.get(0);
180         if (constraints != null) {
181             ArrayList constraintsList = (ArrayList) constraints.get("constraints");
182             if (!CollectionUtils.isEmpty(constraintsList)) {
183                 LinkedHashMap valuesMap = (LinkedHashMap) constraintsList.get(0);
184                 if (valuesMap != null) {
185                     List<Object> values = (List<Object>) valuesMap.get("valid_values");
186                     for (Object value : values) {
187                         String stringValue = value.toString();
188                         LinkedHashMap serviceSpecCharacteristicValue = new LinkedHashMap();
189                         serviceSpecCharacteristicValue.put("isDefault",
190                                 aDefault != null && aDefault.toString().equals(stringValue));
191                         serviceSpecCharacteristicValue.put("value", stringValue);
192                         serviceSpecCharacteristicValue.put("valueType", parameterType);
193                         serviceSpecCharacteristicValues.add(serviceSpecCharacteristicValue);
194                     }
195                 }
196             }
197         }
198     }
199
200
201     private LinkedHashMap getToscaInfosFromResourceUUID(LinkedHashMap nodeTemplates, String name) {
202         if(nodeTemplates!=null) {
203             for (Object nodeTemplateObject : nodeTemplates.values()) {
204                 LinkedHashMap nodeTemplate = (LinkedHashMap) nodeTemplateObject;
205                 LinkedHashMap metadata = (LinkedHashMap) nodeTemplate.get("metadata");
206                 if(metadata.get("UUID")!=null && metadata.get("type")!=null) {
207                     String metadataUUID = (String) metadata.get("UUID");
208                     String metadataType = (String) metadata.get("type");
209                     if ("VF".equalsIgnoreCase(metadataType) && name!=null &&  name.equalsIgnoreCase(metadataUUID)) {
210                         return metadata;
211                     }
212                 }
213             }
214         }
215         return null;
216     }
217
218
219     public Map getToscaInfos(Map sdcResponse) {
220
221         LinkedHashMap topologyTemplate = null;
222
223         String toscaModelUrl = (String) sdcResponse.get("toscaModelURL");
224         String serviceId = (String) sdcResponse.get("id");
225         File toscaFile = sdcClient.callGetWithAttachment(toscaModelUrl);
226         Timestamp timestamp = new Timestamp(System.currentTimeMillis());
227         String tempFolderName = serviceId + timestamp;
228         File folderTemp = null;
229
230         try {
231             unZipArchive(toscaFile.getName(), tempFolderName);
232             folderTemp = new File(tempFolderName);
233             LOGGER.debug("temp folder for tosca files : " + folderTemp.getName());
234
235             LinkedHashMap toscaMetaFileHashMap = parseToscaFile(tempFolderName + "/TOSCA-Metadata/TOSCA.meta");
236             topologyTemplate = getToscaTopologyTemplateNode(tempFolderName, toscaMetaFileHashMap);
237             return topologyTemplate;
238         } catch (TechnicalException e) {
239             LOGGER.error("unable to parse tosca file for id : " + serviceId, e);
240             return  topologyTemplate;
241         }
242         finally {
243             deleteTempFiles(serviceId, toscaFile, folderTemp);
244         }
245
246     }
247
248     private LinkedHashMap getToscaTopologyTemplateNode(String tempFolderName,LinkedHashMap toscaMetaFileHashMap) {
249         LinkedHashMap topologyTemplate = null;
250         if (toscaMetaFileHashMap.get("Entry-Definitions") != null) {
251             String toscaFilePath = (String) toscaMetaFileHashMap.get("Entry-Definitions");
252             LinkedHashMap toscaFileHashMap = parseToscaFile(tempFolderName + "/" + toscaFilePath);
253             if (toscaFileHashMap.get("topology_template") != null) {
254                 topologyTemplate = (LinkedHashMap) toscaFileHashMap.get("topology_template");
255             } else {
256                 LOGGER.error("no Entry-Definitions node in TOSCA.meta");
257             }
258         } else {
259             LOGGER.error("no topology_template node in tosca file");
260         }
261         return topologyTemplate;
262     }
263
264
265     private void deleteTempFiles(String serviceId, File toscaFile, File folderTemp) {
266         try {
267             if(folderTemp!=null){
268                 LOGGER.debug("deleting temp folder for tosca files : " + folderTemp.getName());
269                 FileUtils.deleteDirectory(folderTemp);
270             }
271             LOGGER.debug("deleting tosca archive : " + toscaFile.getName());
272             FileUtils.forceDelete(toscaFile);
273         } catch (IOException e) {
274             LOGGER.error("unable to delete temp directory tosca file for id : " + serviceId, e);
275         }
276     }
277
278     private LinkedHashMap parseToscaFile(String fileName) {
279
280         File toscaFile = new File(fileName);
281         if (!toscaFile.exists()) {
282             throw new TechnicalException("unable to find  file : " + fileName);
283         }
284         try {
285             return (LinkedHashMap) mapper.readValue(toscaFile, Object.class);
286         } catch (IOException e) {
287             LOGGER.warn("unable to parse tosca file : " + fileName, e);
288             throw new TechnicalException("Unable to parse tosca file : " + fileName);
289
290         } catch (NullPointerException e) {
291             LOGGER.warn("unable to find tosca file : " + fileName, e);
292             throw new TechnicalException("unable to find tosca file : " + fileName);
293         }
294     }
295
296
297     /**
298      * Unzip it
299      *
300      * @param zipFile input zip file
301      * @param outputFolder zip file output folder
302      */
303     private void unZipArchive(String zipFile, String outputFolder) {
304
305         byte[] buffer = new byte[1024];
306
307         try {
308
309             // create output directory is not exists
310             File folder = new File(outputFolder);
311             if (!folder.exists()) {
312                 folder.mkdir();
313             }
314
315             // get the zip file content
316             try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
317                 // get the zipped file list entry
318                 ZipEntry ze = zis.getNextEntry();
319
320                 while (ze != null) {
321
322                     String fileName = ze.getName();
323                     File newFile = new File(outputFolder + File.separator + fileName);
324
325                     LOGGER.debug("File to unzip : " + newFile.getAbsoluteFile());
326
327                     // create all non exists folders
328                     // else you will hit FileNotFoundException for compressed folder
329                     new File(newFile.getParent()).mkdirs();
330
331                     try (FileOutputStream fos = new FileOutputStream(newFile)) {
332
333                         int len;
334                         while ((len = zis.read(buffer)) > 0) {
335                             fos.write(buffer, 0, len);
336                         }
337                     }
338                     ze = zis.getNextEntry();
339                 }
340                 zis.closeEntry();
341             }
342
343             LOGGER.debug("Done");
344
345         } catch (IOException ex) {
346             LOGGER.error("Error while unzipping ToscaModel archive from ONAP", ex);
347             throw new TechnicalException("Error while unzipping ToscaModel archive from ONAP");
348         }
349     }
350
351
352 }