0503e34e05175e54bfff510b88306dbeb482b330
[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 java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.sql.Timestamp;
21 import java.util.ArrayList;
22 import java.util.LinkedHashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Map.Entry;
26 import java.util.Set;
27 import java.util.zip.ZipEntry;
28 import java.util.zip.ZipInputStream;
29 import org.apache.commons.collections.CollectionUtils;
30 import org.apache.commons.io.FileUtils;
31 import org.onap.nbi.exceptions.TechnicalException;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34 import org.springframework.beans.factory.annotation.Autowired;
35 import org.springframework.stereotype.Service;
36 import com.fasterxml.jackson.databind.ObjectMapper;
37 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
38
39 @Service
40 public class ToscaInfosProcessor {
41
42     @Autowired
43     SdcClient sdcClient;
44
45     final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); // jackson databind
46
47     private static final Logger LOGGER = LoggerFactory.getLogger(ToscaInfosProcessor.class);
48
49     public void buildResponseWithToscaInfos(LinkedHashMap toscaInfosTopologyTemplate,
50             LinkedHashMap serviceCatalogResponse) {
51         if (toscaInfosTopologyTemplate.get("inputs") != null) {
52             ArrayList serviceSpecCharacteristic = new ArrayList();
53             LinkedHashMap toscaInfos = (LinkedHashMap) toscaInfosTopologyTemplate.get("inputs");
54             Set<Entry<String, LinkedHashMap>> stringLinkedHashMapEntry = (Set<Entry<String, LinkedHashMap>>) toscaInfos
55                 .entrySet();
56
57             for (Map.Entry<String,LinkedHashMap> key :stringLinkedHashMapEntry) {
58                 String keyString = key.getKey();
59                 LinkedHashMap inputParameter = key.getValue();
60                 LinkedHashMap mapParameter = new LinkedHashMap();
61                 String parameterType = (String) inputParameter.get("type");
62                 mapParameter.put("name", keyString);
63                 mapParameter.put("description", inputParameter.get("description"));
64                 mapParameter.put("valueType", parameterType);
65                 mapParameter.put("@type", "ONAPserviceCharacteristic");
66                 mapParameter.put("required", inputParameter.get("required"));
67                 mapParameter.put("status", inputParameter.get("status"));
68                 List<LinkedHashMap> serviceSpecCharacteristicValues =
69                     buildServiceSpecCharacteristicsValues(inputParameter, parameterType);
70                 mapParameter.put("serviceSpecCharacteristicValue", serviceSpecCharacteristicValues);
71                 serviceSpecCharacteristic.add(mapParameter);
72             }
73
74             serviceCatalogResponse.put("serviceSpecCharacteristic", serviceSpecCharacteristic);
75         }
76         LinkedHashMap nodeTemplate = (LinkedHashMap) toscaInfosTopologyTemplate.get("node_templates");
77
78         List<LinkedHashMap> resourceSpecifications =
79                 (List<LinkedHashMap>) serviceCatalogResponse.get("resourceSpecification");
80         for (LinkedHashMap resourceSpecification : resourceSpecifications) {
81             if(resourceSpecification.get("id")!=null){
82                 String id = (String) resourceSpecification.get("id");
83                 LOGGER.debug("get tosca infos for service id: {0}", id);
84                 LinkedHashMap toscaInfosFromResourceId = getToscaInfosFromResourceUUID(nodeTemplate, id);
85                 if (toscaInfosFromResourceId != null && toscaInfosFromResourceId.get("customizationUUID")!=null) {
86                     resourceSpecification.put("modelCustomizationId", toscaInfosFromResourceId.get("customizationUUID"));
87                 }
88             }
89         }
90     }
91
92     private List<LinkedHashMap> buildServiceSpecCharacteristicsValues(LinkedHashMap parameter, String parameterType) {
93         List<LinkedHashMap> serviceSpecCharacteristicValues = new ArrayList<>();
94         if (!"map".equalsIgnoreCase(parameterType) && !"list".equalsIgnoreCase(parameterType)) {
95             LOGGER.debug("get tosca infos for serviceSpecCharacteristicValues of type map or string : {0}", parameter);
96             Object aDefault = parameter.get("default");
97             if (parameter.get("entry_schema") != null) {
98                 ArrayList entrySchema = (ArrayList) parameter.get("entry_schema");
99                 if (CollectionUtils.isNotEmpty(entrySchema)) {
100                     buildCharacteristicValuesFormShema(parameterType, serviceSpecCharacteristicValues, aDefault,
101                             entrySchema);
102                 }
103             }
104         }
105         return serviceSpecCharacteristicValues;
106     }
107
108     private void buildCharacteristicValuesFormShema(String parameterType,
109             List<LinkedHashMap> serviceSpecCharacteristicValues, Object aDefault, ArrayList entry_schema) {
110         LinkedHashMap constraints = (LinkedHashMap) entry_schema.get(0);
111         if (constraints != null) {
112             ArrayList constraintsList = (ArrayList) constraints.get("constraints");
113             if (CollectionUtils.isNotEmpty(constraintsList)) {
114                 LinkedHashMap valuesMap = (LinkedHashMap) constraintsList.get(0);
115                 if (valuesMap != null) {
116                     List<Object> values = (List<Object>) valuesMap.get("valid_values");
117                     for (Object value : values) {
118                         String stringValue = value.toString();
119                         LinkedHashMap serviceSpecCharacteristicValue = new LinkedHashMap();
120                         serviceSpecCharacteristicValue.put("isDefault",
121                                 aDefault != null && aDefault.toString().equals(stringValue));
122                         serviceSpecCharacteristicValue.put("value", stringValue);
123                         serviceSpecCharacteristicValue.put("valueType", parameterType);
124                         serviceSpecCharacteristicValues.add(serviceSpecCharacteristicValue);
125                     }
126                 }
127             }
128         }
129     }
130
131
132     private LinkedHashMap getToscaInfosFromResourceUUID(LinkedHashMap node_templates, String name) {
133         if(node_templates!=null) {
134             for (Object nodeTemplateObject : node_templates.values()) {
135                 LinkedHashMap nodeTemplate = (LinkedHashMap) nodeTemplateObject;
136                 LinkedHashMap metadata = (LinkedHashMap) nodeTemplate.get("metadata");
137                 if(metadata.get("UUID")!=null && metadata.get("type")!=null) {
138                     String metadataUUID = (String) metadata.get("UUID");
139                     String metadataType = (String) metadata.get("type");
140                     if ("VF".equalsIgnoreCase(metadataType) && name!=null &&  name.equalsIgnoreCase(metadataUUID)) {
141                         return metadata;
142                     }
143                 }
144             }
145         }
146         return null;
147     }
148
149
150     public LinkedHashMap getToscaInfos(LinkedHashMap sdcResponse) {
151
152         LinkedHashMap topologyTemplate = null;
153
154         String toscaModelUrl = (String) sdcResponse.get("toscaModelURL");
155         String serviceId = (String) sdcResponse.get("id");
156         File toscaFile = sdcClient.callGetWithAttachment(toscaModelUrl);
157         Timestamp timestamp = new Timestamp(System.currentTimeMillis());
158         String tempFolderName = serviceId + timestamp;
159         File folderTemp = null;
160
161         try {
162             unZipArchive(toscaFile.getName(), tempFolderName);
163             folderTemp = new File(tempFolderName);
164             LOGGER.debug("temp folder for tosca files : " + folderTemp.getName());
165
166             LinkedHashMap toscaMetaFileHashMap = parseToscaFile(tempFolderName + "/TOSCA-Metadata/TOSCA.meta");
167             topologyTemplate = getToscaTopologyTemplateNode(tempFolderName, toscaMetaFileHashMap);
168             return topologyTemplate;
169         } catch (TechnicalException e) {
170             LOGGER.error("unable to parse tosca file for id : " + serviceId, e);
171             return  topologyTemplate;
172         }
173         finally {
174             deleteTempFiles(serviceId, toscaFile, folderTemp);
175         }
176
177     }
178
179     private LinkedHashMap getToscaTopologyTemplateNode(String tempFolderName,LinkedHashMap toscaMetaFileHashMap) {
180         LinkedHashMap topologyTemplate = null;
181         if (toscaMetaFileHashMap.get("Entry-Definitions") != null) {
182             String toscaFilePath = (String) toscaMetaFileHashMap.get("Entry-Definitions");
183             LinkedHashMap toscaFileHashMap = parseToscaFile(tempFolderName + "/" + toscaFilePath);
184             if (toscaFileHashMap.get("topology_template") != null) {
185                 topologyTemplate = (LinkedHashMap) toscaFileHashMap.get("topology_template");
186             } else {
187                 LOGGER.error("no Entry-Definitions node in TOSCA.meta");
188             }
189         } else {
190             LOGGER.error("no topology_template node in tosca file");
191         }
192         return topologyTemplate;
193     }
194
195
196     private void deleteTempFiles(String serviceId, File toscaFile, File folderTemp) {
197         try {
198             if(folderTemp!=null){
199                 LOGGER.debug("deleting temp folder for tosca files : " + folderTemp.getName());
200                 FileUtils.deleteDirectory(folderTemp);
201             }
202             LOGGER.debug("deleting tosca archive : " + toscaFile.getName());
203             FileUtils.forceDelete(toscaFile);
204         } catch (IOException e) {
205             LOGGER.error("unable to delete temp directory tosca file for id : " + serviceId, e);
206         }
207     }
208
209     private LinkedHashMap parseToscaFile(String fileName) {
210
211         File toscaFile = new File(fileName);
212         if (!toscaFile.exists()) {
213             throw new TechnicalException("unable to find  file : " + fileName);
214         }
215         try {
216             return (LinkedHashMap) mapper.readValue(toscaFile, Object.class);
217         } catch (IOException e) {
218             LOGGER.warn("unable to parse tosca file : " + fileName, e);
219             throw new TechnicalException("Unable to parse tosca file : " + fileName);
220
221         } catch (NullPointerException e) {
222             LOGGER.warn("unable to find tosca file : " + fileName, e);
223             throw new TechnicalException("unable to find tosca file : " + fileName);
224         }
225     }
226
227
228     /**
229      * Unzip it
230      *
231      * @param zipFile input zip file
232      * @param outputFolder zip file output folder
233      */
234     private void unZipArchive(String zipFile, String outputFolder) {
235
236         byte[] buffer = new byte[1024];
237
238         try {
239
240             // create output directory is not exists
241             File folder = new File(outputFolder);
242             if (!folder.exists()) {
243                 folder.mkdir();
244             }
245
246             // get the zip file content
247             try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
248                 // get the zipped file list entry
249                 ZipEntry ze = zis.getNextEntry();
250
251                 while (ze != null) {
252
253                     String fileName = ze.getName();
254                     File newFile = new File(outputFolder + File.separator + fileName);
255
256                     LOGGER.debug("File to unzip : " + newFile.getAbsoluteFile());
257
258                     // create all non exists folders
259                     // else you will hit FileNotFoundException for compressed folder
260                     new File(newFile.getParent()).mkdirs();
261
262                     try (FileOutputStream fos = new FileOutputStream(newFile)) {
263
264                         int len;
265                         while ((len = zis.read(buffer)) > 0) {
266                             fos.write(buffer, 0, len);
267                         }
268
269                         fos.close();
270                     }
271                     ze = zis.getNextEntry();
272                 }
273
274                 zis.closeEntry();
275                 zis.close();
276             }
277
278             LOGGER.debug("Done");
279
280         } catch (IOException ex) {
281             LOGGER.error("Error while unzipping ToscaModel archive from ONAP", ex);
282             throw new TechnicalException("Error while unzipping ToscaModel archive from ONAP");
283         }
284     }
285
286
287 }