739ed5ed2a1cc02da152268f075af1c39a3e1260
[vfc/nfvo/catalog.git] /
1 /**
2  * Copyright 2016 [ZTE] and others.
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
17 package org.openo.commontosca.catalog.model.parser;
18
19 import org.openo.commontosca.catalog.common.MsbAddrConfig;
20 import org.openo.commontosca.catalog.common.ToolUtil;
21 import org.openo.commontosca.catalog.db.exception.CatalogResourceException;
22 import org.openo.commontosca.catalog.db.resource.TemplateManager;
23 import org.openo.commontosca.catalog.entity.response.CsarFileUriResponse;
24 import org.openo.commontosca.catalog.model.common.TemplateDataHelper;
25 import org.openo.commontosca.catalog.model.entity.EnumDataType;
26 import org.openo.commontosca.catalog.model.entity.InputParameter;
27 import org.openo.commontosca.catalog.model.entity.NodeTemplate;
28 import org.openo.commontosca.catalog.model.entity.OutputParameter;
29 import org.openo.commontosca.catalog.model.entity.RelationShip;
30 import org.openo.commontosca.catalog.model.entity.ServiceTemplate;
31 import org.openo.commontosca.catalog.model.entity.ServiceTemplateOperation;
32 import org.openo.commontosca.catalog.model.entity.SubstitutionMapping;
33 import org.openo.commontosca.catalog.model.parser.yaml.YamlParseServiceConsumer;
34 import org.openo.commontosca.catalog.model.parser.yaml.entity.EnumYamlServiceTemplateInfo;
35 import org.openo.commontosca.catalog.model.parser.yaml.entity.ParseYamlRequestParemeter;
36 import org.openo.commontosca.catalog.model.parser.yaml.entity.ParseYamlResult;
37 import org.openo.commontosca.catalog.model.parser.yaml.entity.ParseYamlResult.Plan;
38 import org.openo.commontosca.catalog.model.parser.yaml.entity.ParseYamlResult.Plan.PlanValue.PlanInput;
39 import org.openo.commontosca.catalog.model.parser.yaml.entity.ParseYamlResult.TopologyTemplate.Input;
40 import org.openo.commontosca.catalog.model.parser.yaml.entity.ParseYamlResult.TopologyTemplate.NodeTemplate.Relationship;
41 import org.openo.commontosca.catalog.model.parser.yaml.entity.ParseYamlResult.TopologyTemplate.Output;
42 import org.openo.commontosca.catalog.model.plan.wso2.Wso2ServiceConsumer;
43 import org.openo.commontosca.catalog.model.plan.wso2.entity.DeployPackageResponse;
44 import org.openo.commontosca.catalog.wrapper.PackageWrapper;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import java.io.BufferedInputStream;
49 import java.io.BufferedReader;
50 import java.io.File;
51 import java.io.FileInputStream;
52 import java.io.IOException;
53 import java.io.InputStream;
54 import java.io.InputStreamReader;
55 import java.util.ArrayList;
56 import java.util.HashMap;
57 import java.util.List;
58 import java.util.Map;
59 import java.util.zip.ZipEntry;
60 import java.util.zip.ZipFile;
61 import java.util.zip.ZipInputStream;
62
63
64 public class ToscaYamlModelParser extends AbstractModelParser {
65
66   private static final Object TOSCA_META_FIELD_ENTRY_DEFINITIONS = "Entry-Definitions";
67   private static final Logger LOGGER = LoggerFactory.getLogger(ToscaYamlModelParser.class);
68
69   @Override
70   public String parse(String packageId, String fileLocation) throws CatalogResourceException {
71     ParseYamlResult result = getParseYamlResult(fileLocation);
72     
73     Map<String, String> toscaMeta = parseToscaMeta(fileLocation);
74     String stFileName = toscaMeta.get(TOSCA_META_FIELD_ENTRY_DEFINITIONS);
75     CsarFileUriResponse stDownloadUri =
76         PackageWrapper.getInstance().getCsarFileDownloadUri(packageId, stFileName);
77
78     ServiceTemplate st = parseServiceTemplate(packageId, result, stDownloadUri.getDownloadUri());
79     ServiceTemplateOperation[] operations = parseOperations(result.getPlanList(), fileLocation);
80     st.setOperations(operations);
81     List<NodeTemplate> ntList = parseNodeTemplates(packageId, st.getServiceTemplateId(), result);
82     st.setType(getTemplateType(result, ntList).toString());
83
84     TemplateManager.getInstance().addServiceTemplate(
85         TemplateDataHelper.convert2TemplateData(st, ToolUtil.toJson(result), ntList));
86
87     SubstitutionMapping stm = parseSubstitutionMapping(st.getServiceTemplateId(), result);
88     if (stm != null) {
89       TemplateManager.getInstance()
90           .addServiceTemplateMapping(TemplateDataHelper.convert2TemplateMappingData(stm));
91     }
92
93     return st.getServiceTemplateId();
94   }
95
96   private ParseYamlResult getParseYamlResult(String fileLocation) throws CatalogResourceException {
97     String destPath = copyTemporaryFile2HttpServer(fileLocation);
98     try {
99       String url = getUrl(toTempFileLocalPath(fileLocation));
100       return YamlParseServiceConsumer.getServiceTemplates(comboRequest(url));
101     } finally {
102       if (destPath != null && !destPath.isEmpty() && (new File(destPath)).exists()) {
103         (new File(destPath)).delete();
104       }
105     }
106   }
107
108   private String toTempFileLocalPath(String fileLocation) {
109     return File.separator + "temp" + File.separator + (new File(fileLocation)).getName();
110   }
111   
112   private String getUrl(String uri) {
113     String url = null;
114     if ((MsbAddrConfig.getMsbAddress().endsWith("/")) && uri.startsWith("/")) {
115       url = MsbAddrConfig.getMsbAddress() + uri.substring(1);
116     }
117     url = MsbAddrConfig.getMsbAddress() + uri;
118     String urlresult = url.replace("\\", "/");
119     return urlresult;
120   }
121
122   private String copyTemporaryFile2HttpServer(String fileLocation) throws CatalogResourceException {
123     String destPath = Class.class.getClass().getResource("/").getPath()
124         + org.openo.commontosca.catalog.filemanage.http.ToolUtil.getHttpServerPath()
125         + toTempFileLocalPath(fileLocation);
126     if (!org.openo.commontosca.catalog.filemanage.http.ToolUtil.copyFile(fileLocation, destPath,
127         true)) {
128       throw new CatalogResourceException("Copy Temporary To HttpServer Failed.");
129     }
130     return destPath;
131   }
132
133   @SuppressWarnings("resource")
134   private Map<String, String> parseToscaMeta(String fileLocation) throws CatalogResourceException {
135     Map<String, String> toscaMeta = new HashMap<>();
136
137     ZipInputStream zin = null;
138     BufferedReader br = null;
139     try {
140       InputStream in = new BufferedInputStream(new FileInputStream(fileLocation));
141       zin = new ZipInputStream(in);
142       ZipEntry ze;
143       while ((ze = zin.getNextEntry()) != null) {
144         if (("TOSCA-Metadata" + File.separator + "TOSCA.meta").equals(ze.getName())
145             || "TOSCA-Metadata/TOSCA.meta".equals(ze.getName())) {
146           ZipFile zf = new ZipFile(fileLocation);
147           br = new BufferedReader(new InputStreamReader(zf.getInputStream(ze)));
148           String line;
149           String[] tmps;
150           while ((line = br.readLine()) != null) {
151             if (line.indexOf(":") > 0) {
152               tmps = line.split(":");
153               toscaMeta.put(tmps[0].trim(), tmps[1].trim());
154             }
155           }
156
157           return toscaMeta;
158         }
159       }
160
161     } catch (IOException e1) {
162       throw new CatalogResourceException("Parse Tosca Meta Fail.", e1);
163     } finally {
164       closeStreamAndReader(zin, br);
165     }
166
167     return toscaMeta;
168   }
169
170   private void closeStreamAndReader(ZipInputStream zin, BufferedReader br) {
171     if (br != null) {
172       try {
173         br.close();
174       } catch (IOException e1) {
175         LOGGER.error("Buffered reader close failed !");
176       }
177     }
178     if (zin != null) {
179       try {
180         zin.closeEntry();
181       } catch (IOException e2) {
182         LOGGER.error("Zip inputStream close failed !");
183       }
184     }
185   }
186
187   private ParseYamlRequestParemeter comboRequest(String fileLocation) {
188     ParseYamlRequestParemeter request = new ParseYamlRequestParemeter();
189     request.setPath(fileLocation);
190     return request;
191   }
192
193   private SubstitutionMapping parseSubstitutionMapping(String serviceTemplateId,
194       ParseYamlResult result) {
195     String type = getSubstitutionMappingType(result);
196     if (ToolUtil.isTrimedEmptyString(type)) {
197       return null;
198     }
199
200     org.openo.commontosca.catalog.model.parser.yaml.entity.ParseYamlResult
201         .TopologyTemplate.SubstitutionMapping stm =
202         result.getTopologyTemplate().getSubstitutionMappings();
203     return new SubstitutionMapping(serviceTemplateId, type, stm.getRequirementList(),
204         stm.getCapabilityList());
205   }
206
207   private ServiceTemplate parseServiceTemplate(String packageId, ParseYamlResult result,
208       String stDownloadUri) {
209     ServiceTemplate st = new ServiceTemplate();
210
211     st.setServiceTemplateId(ToolUtil.generateId());
212     st.setTemplateName(result.getMetadata().get(EnumYamlServiceTemplateInfo.ID.getName()));
213     st.setVendor(result.getMetadata().get(EnumYamlServiceTemplateInfo.PROVIDER.getName()));
214     st.setVersion(result.getMetadata().get(EnumYamlServiceTemplateInfo.VERSION.getName()));
215     st.setCsarid(packageId);
216     st.setDownloadUri(stDownloadUri);
217     st.setInputs(parseInputs(result));
218     st.setOutputs(parseOutputs(result));
219     return st;
220   }
221
222   private InputParameter[] parseInputs(ParseYamlResult result) {
223     List<Input> inputList = result.getTopologyTemplate().getInputs();
224     if (inputList == null) {
225       return new InputParameter[0];
226     }
227     List<InputParameter> retList = new ArrayList<InputParameter>();
228     for (Input input : inputList) {
229       retList.add(new InputParameter(input.getName(), getEnumDataType(input.getType()),
230           input.getDescription(), input.getDefault(), input.isRequired()));
231     }
232     return retList.toArray(new InputParameter[0]);
233   }
234
235   private OutputParameter[] parseOutputs(ParseYamlResult result) {
236     List<Output> outputList = result.getTopologyTemplate().getOutputs();
237     if (outputList == null || outputList.isEmpty()) {
238       return new OutputParameter[0];
239     }
240     List<OutputParameter> retList = new ArrayList<OutputParameter>();
241     for (Output output : outputList) {
242       retList
243           .add(new OutputParameter(output.getName(), output.getDescription(), output.getValue()));
244     }
245     return retList.toArray(new OutputParameter[0]);
246   }
247
248   private ServiceTemplateOperation[] parseOperations(List<Plan> planList, String zipFileLocation)
249       throws CatalogResourceException {
250     if (planList == null || planList.isEmpty()) {
251       return new ServiceTemplateOperation[0];
252     }
253
254     List<ServiceTemplateOperation> opList = new ArrayList<>();
255     for (Plan plan : planList) {
256       ServiceTemplateOperation op = new ServiceTemplateOperation();
257       op.setName(plan.getName());
258       op.setDescription(plan.getDescription());
259       checkPlanLanguage(plan.getPlanLanguage());
260       DeployPackageResponse response =
261           Wso2ServiceConsumer.deployPackage(zipFileLocation, plan.getReference());
262       op.setPackageName(parsePackageName(response));
263       op.setProcessId(response.getProcessId());
264       op.setInputs(parsePlanInputs(plan.getInputList()));
265
266       opList.add(op);
267
268     }
269     return opList.toArray(new ServiceTemplateOperation[0]);
270   }
271
272   private String parsePackageName(DeployPackageResponse response) {
273     String packageName = response.getPackageName();
274     if (packageName != null && packageName.indexOf("-") > 0) {
275       packageName = packageName.substring(0, packageName.lastIndexOf("-"));
276     }
277     return packageName;
278   }
279
280   private void checkPlanLanguage(String planLanguage) throws CatalogResourceException {
281     if (planLanguage == null || planLanguage.isEmpty()) {
282       throw new CatalogResourceException("Plan Language is empty.");
283     }
284     if (planLanguage.equalsIgnoreCase("bpel")) {
285       return;
286     }
287     if (planLanguage.equalsIgnoreCase("bpmn")) {
288       return;
289     }
290     if (planLanguage.equalsIgnoreCase("bpmn4tosca")) {
291       return;
292     }
293     throw new CatalogResourceException(
294         "Plan Language is not supported. Language = " + planLanguage);
295   }
296
297   private InputParameter[] parsePlanInputs(List<PlanInput> inputList) {
298     if (inputList == null || inputList.isEmpty()) {
299       return new InputParameter[0];
300     }
301
302     List<InputParameter> retList = new ArrayList<>();
303     for (PlanInput input : inputList) {
304       retList.add(new InputParameter(input.getName(), getEnumDataType(input.getType()),
305           input.getDescription(), input.getDefault(), input.isRequired()));
306     }
307     return retList.toArray(new InputParameter[0]);
308   }
309
310   private EnumDataType getEnumDataType(String type) {
311     if (EnumDataType.INTEGER.toString().equalsIgnoreCase(type)) {
312       return EnumDataType.INTEGER;
313     }
314
315     if (EnumDataType.FLOAT.toString().equalsIgnoreCase(type)) {
316       return EnumDataType.FLOAT;
317     }
318
319     if (EnumDataType.BOOLEAN.toString().equalsIgnoreCase(type)) {
320       return EnumDataType.BOOLEAN;
321     }
322
323     return EnumDataType.STRING;
324   }
325
326   private List<NodeTemplate> parseNodeTemplates(String csarId, String templateId,
327       ParseYamlResult result) {
328     List<ParseYamlResult.TopologyTemplate.NodeTemplate> nodetemplateList =
329         result.getTopologyTemplate().getNodeTemplates();
330     if (nodetemplateList == null) {
331       return null;
332     }
333
334     List<NodeTemplate> retList = new ArrayList<>();
335     for (ParseYamlResult.TopologyTemplate.NodeTemplate nodeTemplate : nodetemplateList) {
336       NodeTemplate ret = new NodeTemplate();
337       ret.setId(nodeTemplate.getName());
338       ret.setName(nodeTemplate.getName());
339       ret.setType(nodeTemplate.getNodeType());
340       ret.setProperties(nodeTemplate.getPropertyList());
341       List<RelationShip> relationShipList =
342           parseNodeTemplateRelationShip(nodeTemplate.getRelationships());
343       ret.setRelationShips(relationShipList);
344
345       retList.add(ret);
346     }
347
348     return retList;
349   }
350
351
352   private List<RelationShip> parseNodeTemplateRelationShip(List<Relationship> relationshipList) {
353     List<RelationShip> retList = new ArrayList<>();
354
355     if (relationshipList == null) {
356       return retList;
357     }
358
359     for (Relationship relationship : relationshipList) {
360       RelationShip ret = new RelationShip();
361       ret.setSourceNodeId(relationship.getSourceNodeName());
362       ret.setSourceNodeName(relationship.getSourceNodeName());
363       ret.setTargetNodeId(relationship.getTargetNodeName());
364       ret.setTargetNodeName(relationship.getTargetNodeName());
365       ret.setType(relationship.getType());
366       retList.add(ret);
367     }
368
369     return retList;
370   }
371
372   private EnumTemplateType getTemplateType(ParseYamlResult result, List<NodeTemplate> ntList) {
373     String type = getSubstitutionMappingType(result);
374     if (isNsType(type)) {
375       return EnumTemplateType.NS;
376     }
377
378     if (isVnfType(type)) {
379       return EnumTemplateType.VNF;
380     }
381
382     return getTemplateTypeFromNodeTemplates(ntList);
383   }
384
385   private String getSubstitutionMappingType(ParseYamlResult result) {
386     if (result.getTopologyTemplate().getSubstitutionMappings() == null) {
387       return null;
388     }
389     return result.getTopologyTemplate().getSubstitutionMappings().getNodeType();
390   }
391
392   private EnumTemplateType getTemplateTypeFromNodeTemplates(List<NodeTemplate> ntList) {
393     for (NodeTemplate nt : ntList) {
394       if (isNsType(nt.getType()) || isVnfType(nt.getType())) {
395         return EnumTemplateType.NS;
396       }
397     }
398
399     return EnumTemplateType.VNF;
400   }
401
402   private boolean isVnfType(String type) {
403     if (ToolUtil.isTrimedEmptyString(type)) {
404       return false;
405     }
406     return type.toUpperCase().contains(".VNF");
407   }
408
409   private boolean isNsType(String type) {
410     if (ToolUtil.isTrimedEmptyString(type)) {
411       return false;
412     }
413     return type.toUpperCase().contains(".NS");
414   }
415 }