SRIOV - add annotations
[sdc.git] / openecomp-be / lib / openecomp-sdc-translator-lib / openecomp-sdc-translator-core / src / main / java / org / openecomp / sdc / translator / services / heattotosca / TranslationService.java
1 /*
2  * Copyright © 2018 European Support Limited
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.openecomp.sdc.translator.services.heattotosca;
18
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.apache.commons.collections4.MapUtils;
21 import org.openecomp.core.translator.datatypes.TranslatorOutput;
22 import org.openecomp.core.utilities.file.FileUtils;
23 import org.openecomp.sdc.common.errors.CoreException;
24 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
25 import org.openecomp.sdc.heat.datatypes.model.Environment;
26 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
27 import org.openecomp.sdc.heat.datatypes.model.Output;
28 import org.openecomp.sdc.heat.datatypes.model.Resource;
29 import org.openecomp.sdc.logging.api.Logger;
30 import org.openecomp.sdc.logging.api.LoggerFactory;
31 import org.openecomp.sdc.tosca.datatypes.ToscaGroupType;
32 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
33 import org.openecomp.sdc.tosca.datatypes.model.GroupDefinition;
34 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
35 import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
36 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
37 import org.openecomp.sdc.tosca.datatypes.model.TopologyTemplate;
38 import org.openecomp.sdc.tosca.datatypes.model.heatextend.ParameterDefinitionExt;
39 import org.openecomp.sdc.tosca.services.DataModelUtil;
40 import org.openecomp.sdc.tosca.services.ToscaConstants;
41 import org.openecomp.sdc.tosca.services.ToscaFileOutputService;
42 import org.openecomp.sdc.tosca.services.ToscaUtil;
43 import org.openecomp.sdc.tosca.services.YamlUtil;
44 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
45 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
46 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
47 import org.openecomp.sdc.translator.datatypes.heattotosca.to.FileDataCollection;
48 import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder;
49 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
50 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaParameterConverter;
51
52 import java.util.ArrayList;
53 import java.util.HashMap;
54 import java.util.HashSet;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Objects;
58 import java.util.Optional;
59 import java.util.Set;
60 import java.util.stream.Collectors;
61
62 public class TranslationService {
63
64     protected static Logger logger = LoggerFactory.getLogger(TranslationService.class);
65
66     /**
67      * Gets types to process by translator.
68      *
69      * @return the types to process by translator
70      */
71     public static Set<FileData.Type> getTypesToProcessByTranslator() {
72         Set<FileData.Type> types = new HashSet<>();
73         types.add(FileData.Type.HEAT);
74         types.add(FileData.Type.HEAT_VOL);
75         return types;
76     }
77
78     /**
79      * Translate heat files translator output.
80      *
81      * @param translationContext the translation context
82      * @return the translator output
83      */
84     public TranslatorOutput translateHeatFiles(TranslationContext translationContext) {
85         ServiceTemplate mainServiceTemplate = createMainServiceTemplate(translationContext);
86         List<FileData> fileDataList = translationContext.getManifest().getContent().getData();
87         FileDataCollection fileDataCollection = HeatToToscaUtil.getFileCollectionsByFilter(fileDataList,
88                 TranslationService.getTypesToProcessByTranslator(), translationContext);
89
90         if (fileDataCollection.getBaseFile() != null) {
91             for (FileData fileData : fileDataCollection.getBaseFile()) {
92                 translateHeatFile(mainServiceTemplate, fileData, translationContext);
93             }
94         }
95         if (fileDataCollection.getAddOnFiles() != null) {
96             for (FileData fileData : fileDataCollection.getAddOnFiles()) {
97                 translateHeatFile(mainServiceTemplate, fileData, translationContext);
98             }
99         }
100
101         ToscaServiceModel toscaServiceModel =
102                 HeatToToscaUtil.createToscaServiceModel(mainServiceTemplate, translationContext);
103
104         TranslatorOutput translatorOutput = new TranslatorOutput();
105         //Keeping a copy of tosca service model after first stage of translation for extraction of
106         // composition data
107         translatorOutput.setNonUnifiedToscaServiceModel(
108                 ToscaServiceModel.getClonedServiceModel(toscaServiceModel));
109         translatorOutput.setToscaServiceModel(toscaServiceModel);
110         return translatorOutput;
111     }
112
113     private ServiceTemplate createMainServiceTemplate(TranslationContext translationContext) {
114         ServiceTemplate mainServiceTemplate = new ServiceTemplate();
115         translationContext.getTranslatedServiceTemplates()
116                 .put(Constants.MAIN_TEMPLATE_NAME, mainServiceTemplate);
117         Map<String, String> templateMetadata = new HashMap<>();
118         templateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, Constants.MAIN_TEMPLATE_NAME);
119         mainServiceTemplate.setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
120         mainServiceTemplate.setMetadata(templateMetadata);
121         mainServiceTemplate.setTopology_template(new TopologyTemplate());
122         mainServiceTemplate.setImports(GlobalTypesGenerator.getGlobalTypesImportList());
123         return mainServiceTemplate;
124     }
125
126     /**
127      * Translate heat file.
128      *
129      * @param serviceTemplate the service template
130      * @param heatFileData    the heat file data
131      * @param context         the context
132      */
133     public void translateHeatFile(ServiceTemplate serviceTemplate, FileData heatFileData,
134                                   TranslationContext context) {
135         String heatFileName = heatFileData.getFile();
136         HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil()
137                 .yamlToObject(context.getFileContent(heatFileName), HeatOrchestrationTemplate.class);
138
139         translateInputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData, context,
140                 heatFileName);
141         translateResources(heatFileName, serviceTemplate, heatOrchestrationTemplate, context);
142         translateOutputParameters(serviceTemplate, heatOrchestrationTemplate, heatFileData,
143                 heatFileName, context);
144         createHeatStackGroup(serviceTemplate, heatFileData, heatOrchestrationTemplate, context);
145         handleHeatPseudoParam(heatFileName, serviceTemplate, context);
146
147         if (Objects.nonNull(heatFileData.getData())) {
148             heatFileData.getData().stream().filter(data -> data.getType() == FileData.Type.HEAT_VOL)
149                     .forEach(data -> translateHeatFile(serviceTemplate, data, context));
150         }
151     }
152
153     private void handleHeatPseudoParam(String heatFileName, ServiceTemplate serviceTemplate,
154                                        TranslationContext context) {
155         Map<String, String> translatedHeatPseudoParam =
156                 context.getUsedHeatPseudoParams().get(heatFileName);
157         if (Objects.nonNull(translatedHeatPseudoParam)) {
158             for (String heatPseudoParam : translatedHeatPseudoParam.keySet()) {
159                 if (!serviceTemplate.getTopology_template().getInputs().containsKey(heatPseudoParam)) {
160                     ParameterDefinition parameterDefinition = new ParameterDefinition();
161                     parameterDefinition.setType(PropertyType.STRING.getDisplayName());
162                     parameterDefinition.setRequired(false);
163                     String parameterDefinitionId = translatedHeatPseudoParam.get(heatPseudoParam);
164                     DataModelUtil.addInputParameterToTopologyTemplate(serviceTemplate, parameterDefinitionId,
165                             parameterDefinition);
166                 }
167             }
168         }
169     }
170
171     private void createHeatStackGroup(ServiceTemplate serviceTemplate, FileData heatFileData,
172                                       HeatOrchestrationTemplate heatOrchestrationTemplate,
173                                       TranslationContext context) {
174         ToscaFileOutputService toscaFileOutputService = new ToscaFileOutputServiceCsarImpl();
175         final String fileName = heatFileData.getFile();
176         final String heatStackGroupId = FileUtils.getFileWithoutExtention(fileName) + "_group";
177
178         GroupDefinition groupDefinition = new GroupDefinition();
179         groupDefinition.setType(ToscaGroupType.HEAT_STACK);
180         groupDefinition.setProperties(new HashMap<>());
181         groupDefinition.getProperties()
182                 .put("heat_file", "../" + toscaFileOutputService.getArtifactsFolderName() + "/" + fileName);
183         String hotDescription = heatOrchestrationTemplate.getDescription();
184         if (hotDescription != null && !hotDescription.isEmpty()) {
185             groupDefinition.getProperties().put(Constants.DESCRIPTION_PROPERTY_NAME, hotDescription);
186         }
187         groupDefinition.setMembers(new ArrayList<>());
188         Set<String> heatStackGroupMembersIds = getHeatStackGroupMembers(fileName,
189                 serviceTemplate, context);
190         if (CollectionUtils.isEmpty(heatStackGroupMembersIds)) {
191             return; //not creating a group when no resources are present in the heat input
192         }
193         groupDefinition.getMembers().addAll(heatStackGroupMembersIds);
194         DataModelUtil
195                 .addGroupDefinitionToTopologyTemplate(serviceTemplate, heatStackGroupId, groupDefinition);
196     }
197
198     private Set<String> getHeatStackGroupMembers(String heatFileName,
199                                                  ServiceTemplate serviceTemplate,
200                                                  TranslationContext context) {
201
202         Map<String, Set<String>> heatStackGroupMembers = context.getHeatStackGroupMembers();
203         Set<String> groupMembers = MapUtils.isEmpty(heatStackGroupMembers) ? new HashSet<>()
204                 : heatStackGroupMembers.get(heatFileName);
205
206         if (CollectionUtils.isEmpty(groupMembers)) {
207             return new HashSet<>();
208         }
209
210         Set<String> updatedMembersIds = new HashSet<>();
211
212         groupMembers.forEach(member -> {
213             if (Objects.nonNull(DataModelUtil.getNodeTemplate(serviceTemplate, member))) {
214                 updatedMembersIds.add(member);
215             } else {
216                 updateSubstitutableGroupMemberId(heatFileName, serviceTemplate, updatedMembersIds);
217             }
218         });
219
220         return updatedMembersIds;
221     }
222
223     private void updateSubstitutableGroupMemberId(String heatFileName,
224                                                   ServiceTemplate serviceTemplate,
225                                                   Set<String> updatedMembersIds) {
226         Optional<String> substitutableGroupMemberId =
227                 ToscaUtil.getSubstitutableGroupMemberId(heatFileName, serviceTemplate);
228
229         substitutableGroupMemberId.ifPresent(updatedMembersIds::add);
230     }
231
232     private void translateInputParameters(ServiceTemplate serviceTemplate,
233                                           HeatOrchestrationTemplate heatOrchestrationTemplate,
234                                           FileData heatFileData, TranslationContext context,
235                                           String heatFileName) {
236         if (heatOrchestrationTemplate.getParameters() == null) {
237             return;
238         }
239
240         Map<String, ParameterDefinition> parameterDefinitionMap =
241                 TranslatorHeatToToscaParameterConverter
242                         .parameterConverter(serviceTemplate, heatOrchestrationTemplate.getParameters(),
243                                 heatOrchestrationTemplate, heatFileName, context);
244         Environment heatEnvFile = getHeatEnvFile(heatFileData, context);
245         Map<String, Object> parameters = heatEnvFile.getParameters();
246         Object parameterValue;
247         if (parameters != null) {
248             for (Map.Entry<String, ParameterDefinition> entry : parameterDefinitionMap.entrySet()) {
249                 String paramName = entry.getKey();
250                 parameterValue = parameters.get(paramName);
251                 if (parameterValue != null) {
252                     entry.getValue().set_default(TranslatorHeatToToscaParameterConverter
253                             .getToscaParameterDefaultValue(null, null, parameterValue, entry.getValue().getType(),
254                                     heatFileName, heatOrchestrationTemplate, context));
255                 }
256             }
257         }
258
259
260         Map<String, ParameterDefinition> inputs = serviceTemplate.getTopology_template().getInputs();
261         if (Objects.isNull(inputs)) {
262             serviceTemplate.getTopology_template().setInputs(parameterDefinitionMap);
263         } else {
264             setInputs(inputs, parameterDefinitionMap);
265
266         }
267
268     }
269
270     private void setInputs(Map<String, ParameterDefinition> inputs, Map<String, ParameterDefinition> newParameters) {
271
272         updateAnnotations(inputs, newParameters);
273         inputs.putAll(newParameters);
274
275     }
276
277     private void updateAnnotations(Map<String, ParameterDefinition> inputParameters, Map<String, ParameterDefinition> newParameters) {
278
279         if (Objects.nonNull(newParameters.entrySet())) {
280             newParameters.entrySet().stream().filter(stringParameterDefinitionEntry ->
281                     inputParameters.containsKey(stringParameterDefinitionEntry.getKey()) &&
282                             isHasAnnotation(inputParameters, stringParameterDefinitionEntry)).
283                     forEach(stringParameterDefinitionEntry -> getVFModulesList(stringParameterDefinitionEntry.getValue()).
284                             addAll(getVFModulesList(inputParameters.get(stringParameterDefinitionEntry.getKey()))));
285         }
286     }
287
288     private boolean isHasAnnotation(Map<String, ParameterDefinition> inputParameters, Map.Entry<String, ParameterDefinition> newParameterSet) {
289         ParameterDefinitionExt inputParameter = (ParameterDefinitionExt) inputParameters.get(newParameterSet.getKey());
290         ParameterDefinitionExt newParameter = (ParameterDefinitionExt) newParameterSet.getValue();
291         return inputParameter.getAnnotations() != null && newParameter.getAnnotations() != null;
292     }
293
294     private List getVFModulesList(ParameterDefinition param) {
295         ParameterDefinitionExt parameterDefinitionExt = (ParameterDefinitionExt) param;
296         return (List) parameterDefinitionExt.getAnnotations().get(ToscaConstants.SOURCE_ANNOTATION_ID).getProperties().
297                 get(ToscaConstants.VF_MODULE_LABEL_PROPERTY_NAME);
298     }
299
300     private void translateOutputParameters(ServiceTemplate serviceTemplate,
301                                            HeatOrchestrationTemplate heatOrchestrationTemplate,
302                                            FileData heatFileData, String heatFileName,
303                                            TranslationContext context) {
304         if (heatOrchestrationTemplate.getOutputs() == null) {
305             return;
306         }
307         Map<String, ParameterDefinition> parameterDefinitionMap =
308                 TranslatorHeatToToscaParameterConverter
309                         .parameterOutputConverter(serviceTemplate, heatOrchestrationTemplate.getOutputs(),
310                                 heatOrchestrationTemplate, heatFileName, context);
311         if (serviceTemplate.getTopology_template().getOutputs() != null) {
312             serviceTemplate.getTopology_template().getOutputs().putAll(parameterDefinitionMap);
313         } else {
314             serviceTemplate.getTopology_template().setOutputs(parameterDefinitionMap);
315         }
316
317         if (heatFileData.getBase() != null && heatFileData.getBase().equals(true)) {
318             updateSharedResources(serviceTemplate, heatFileName, heatOrchestrationTemplate,
319                     heatOrchestrationTemplate.getOutputs(), context);
320         }
321     }
322
323     private void updateSharedResources(ServiceTemplate serviceTemplate, String heatFileName,
324                                        HeatOrchestrationTemplate heatOrchestrationTemplate,
325                                        Map<String, Output> outputs, TranslationContext context) {
326         for (Map.Entry<String, Output> parameter : outputs.entrySet()) {
327             Optional<AttachedResourceId> attachedSharedResourceId = HeatToToscaUtil
328                     .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context,
329                             parameter.getValue().getValue());
330             if (attachedSharedResourceId.isPresent() && attachedSharedResourceId.get().isGetResource()
331                     && attachedSharedResourceId.get().getTranslatedId() != null) {
332                 String sharedTranslatedResourceId =
333                         attachedSharedResourceId.get().getTranslatedId().toString();
334                 updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
335                         heatOrchestrationTemplate.getResources()
336                                 .get(attachedSharedResourceId.get().getEntityId()));
337             } else {
338                 Optional<String> contrailSharedResourceId = HeatToToscaUtil
339                         .extractContrailGetResourceAttachedHeatResourceId(parameter.getValue().getValue());
340                 if (contrailSharedResourceId.isPresent()
341                         && context.getTranslatedIds().get(heatFileName).get(contrailSharedResourceId.get())
342                         != null) {
343                     String sharedTranslatedResourceId = context.getTranslatedIds().get(heatFileName).get
344                             (contrailSharedResourceId.get());
345                     ConsolidationDataUtil.removeSharedResource(serviceTemplate, heatOrchestrationTemplate,
346                             context, parameter.getKey(), contrailSharedResourceId.get(), sharedTranslatedResourceId);
347                     updateSharedResource(serviceTemplate, context, parameter, sharedTranslatedResourceId,
348                             heatOrchestrationTemplate.getResources().get(contrailSharedResourceId.get()));
349                 }
350             }
351         }
352         if (serviceTemplate.getTopology_template().getOutputs() != null
353                 && serviceTemplate.getTopology_template().getOutputs().size() == 0) {
354             serviceTemplate.getTopology_template().setOutputs(null);
355         }
356     }
357
358     private void updateSharedResource(ServiceTemplate serviceTemplate, TranslationContext context,
359                                       Map.Entry<String, Output> paramName,
360                                       String sharedTranslatedResourceId, Resource resource) {
361         context.addHeatSharedResourcesByParam(paramName.getKey(), sharedTranslatedResourceId, resource);
362         serviceTemplate.getTopology_template().getOutputs().remove(paramName.getKey());
363     }
364
365     private void translateResources(String heatFileName, ServiceTemplate serviceTemplate,
366                                     HeatOrchestrationTemplate heatOrchestrationTemplate,
367                                     TranslationContext context) {
368         if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources())) {
369             return;
370         }
371
372         for (String resourceId : heatOrchestrationTemplate.getResources().keySet()) {
373             Resource resource = heatOrchestrationTemplate.getResources().get(resourceId);
374             if (resource == null) {
375                 throw new CoreException(
376                         new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build());
377             }
378             ResourceTranslationFactory.getInstance(resource)
379                     .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource,
380                             resourceId, context);
381         }
382     }
383
384     private Environment getHeatEnvFile(FileData heatFileData, TranslationContext context) {
385         List<FileData> fileRelatedDataList = heatFileData.getData();
386         if (fileRelatedDataList == null) {
387             return new Environment();
388         }
389         for (FileData fileRelatedData : fileRelatedDataList) {
390             if (fileRelatedData.getType().equals(FileData.Type.HEAT_ENV)) {
391                 return new YamlUtil().yamlToObject(context.getFileContent(fileRelatedData.getFile()),
392                         Environment.class);
393             }
394         }
395         return new Environment();
396     }
397
398
399 }