Support functions in TOSCA Simple Profile in YAML
[sdc.git] / openecomp-be / lib / openecomp-sdc-translator-lib / openecomp-sdc-translator-core / src / main / java / org / openecomp / sdc / translator / services / heattotosca / impl / resourcetranslation / ResourceTranslationContrailServiceInstanceImpl.java
1 /*
2  * Copyright © 2016-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.impl.resourcetranslation;
18
19 import static org.openecomp.sdc.tosca.services.ToscaConstants.MANDATORY_PROPERTY_NAME;
20 import static org.openecomp.sdc.translator.services.heattotosca.HeatToToscaLogConstants.LOG_INVALID_NETWORK_CONNECTION;
21 import static org.openecomp.sdc.translator.services.heattotosca.HeatToToscaLogConstants.LOG_MISSING_VIRTUAL_NETWORK_INTERFACE_LIST;
22 import static org.openecomp.sdc.translator.services.heattotosca.HeatToToscaLogConstants.LOG_MULTIPLE_SERVICE_INSTANCE_DIFF_INTERFACES;
23 import static org.openecomp.sdc.translator.services.heattotosca.HeatToToscaLogConstants.LOG_SERVICE_TEMPLATE_PROPERTY_GET_RESOURCE;
24 import static org.openecomp.sdc.translator.services.heattotosca.HeatToToscaLogConstants.LOG_SERVICE_TEMPLATE_PROPERTY_INVALID_TYPE;
25 import static org.openecomp.sdc.translator.services.heattotosca.HeatToToscaLogConstants.LOG_SERVICE_TEMPLATE_PROPERTY_UNSUPPORTED_RESOURCE;
26 import static org.openecomp.sdc.translator.services.heattotosca.HeatToToscaLogConstants.LOG_UNSUPPORTED_NETWORK_RESOURCE_CONNECTION;
27
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Objects;
33 import java.util.Optional;
34
35 import org.onap.sdc.tosca.datatypes.model.*;
36 import org.openecomp.sdc.common.errors.CoreException;
37 import org.openecomp.sdc.heat.datatypes.HeatBoolean;
38 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
39 import org.openecomp.sdc.heat.datatypes.model.Resource;
40 import org.openecomp.sdc.heat.services.HeatConstants;
41 import org.openecomp.sdc.logging.api.Logger;
42 import org.openecomp.sdc.logging.api.LoggerFactory;
43 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
44 import org.openecomp.sdc.tosca.datatypes.ToscaFunctions;
45 import org.openecomp.sdc.tosca.datatypes.ToscaGroupType;
46 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
47 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
48 import org.openecomp.sdc.tosca.services.DataModelUtil;
49 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
50 import org.openecomp.sdc.tosca.services.ToscaConstants;
51 import org.openecomp.sdc.tosca.services.ToscaUtil;
52 import org.openecomp.sdc.tosca.services.impl.ToscaAnalyzerServiceImpl;
53 import org.openecomp.sdc.tosca.services.impl.ToscaFileOutputServiceCsarImpl;
54 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
55 import org.openecomp.sdc.translator.datatypes.heattotosca.to.ContrailServiceInstanceTo;
56 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
57 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslatedHeatResource;
58 import org.openecomp.sdc.translator.services.heattotosca.Constants;
59 import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil;
60 import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory;
61 import org.openecomp.sdc.translator.services.heattotosca.errors.MissingMandatoryPropertyErrorBuilder;
62 import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator;
63 import org.openecomp.sdc.translator.services.heattotosca.helper.ContrailTranslationHelper;
64 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaPropertyConverter;
65
66 import com.google.common.collect.ImmutableList;
67
68 public class ResourceTranslationContrailServiceInstanceImpl extends ResourceTranslationBase {
69
70     private static final String INTERFACE_LIST = "interface_list";
71     protected static Logger logger = LoggerFactory.getLogger(ResourceTranslationContrailServiceInstanceImpl.class);
72
73     @Override
74     public void translate(TranslateTo translateTo) {
75         Resource serviceInstanceResource = translateTo.getResource();
76         AttachedResourceId contrailServiceTemplateAttached = getServiceTemplateAttachedId(translateTo,
77                 serviceInstanceResource);
78         if (contrailServiceTemplateAttached.isGetResource()) {
79             translateContrailServiceInstance(translateTo, serviceInstanceResource, contrailServiceTemplateAttached);
80         } else {
81             logger.warn(LOG_SERVICE_TEMPLATE_PROPERTY_GET_RESOURCE, translateTo.getResourceId(),
82                     translateTo.getResource().getType());
83         }
84     }
85
86     private void translateContrailServiceInstance(TranslateTo translateTo, Resource serviceInstanceResource,
87                                                   AttachedResourceId contrailServiceTemplateAttached) {
88         String contrailServiceTemplateResourceId = (String) contrailServiceTemplateAttached.getEntityId();
89         Resource contrailServiceTemplateResource = HeatToToscaUtil
90                 .getResource(translateTo.getHeatOrchestrationTemplate(),
91                         contrailServiceTemplateResourceId, translateTo.getHeatFileName());
92         if (!contrailServiceTemplateResource.getType()
93                 .equals(HeatResourcesTypes.CONTRAIL_SERVICE_TEMPLATE.getHeatResource())) {
94             logger.warn(LOG_SERVICE_TEMPLATE_PROPERTY_INVALID_TYPE, translateTo.getResourceId(),
95                     translateTo.getResource().getType(), contrailServiceTemplateResourceId,
96                     contrailServiceTemplateResource.getType(),
97                     HeatResourcesTypes.CONTRAIL_SERVICE_TEMPLATE.getHeatResource());
98             return;
99         }
100         Optional<String> contrailServiceTemplateTranslatedId =
101                 ResourceTranslationFactory.getInstance(contrailServiceTemplateResource)
102                         .translateResource(translateTo.getHeatFileName(), translateTo.getServiceTemplate(),
103                                 translateTo.getHeatOrchestrationTemplate(), contrailServiceTemplateResource,
104                                 contrailServiceTemplateResourceId, translateTo.getContext());
105         if (!contrailServiceTemplateTranslatedId.isPresent()) {
106             logger.warn(LOG_SERVICE_TEMPLATE_PROPERTY_UNSUPPORTED_RESOURCE, translateTo.getResourceId(),
107                     translateTo.getResource().getType(), contrailServiceTemplateResourceId,
108                     contrailServiceTemplateResource.getType());
109             return;
110         }
111
112         ServiceTemplate globalSubstitutionServiceTemplate = translateTo.getContext().getTranslatedServiceTemplates()
113                 .get(Constants.GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME);
114         String contrailStId = ResourceTranslationContrailServiceTemplateImpl
115                 .getContrailSubstitutedNodeTypeId(contrailServiceTemplateTranslatedId.get());
116         NodeType substitutedNodeType = DataModelUtil.getNodeType(globalSubstitutionServiceTemplate, contrailStId);
117         int numberOfPorts = getServiceInstanceNumberOfPorts(serviceInstanceResource);
118         if (substitutedNodeType.getRequirements() != null
119                 && substitutedNodeType.getRequirements().size() != numberOfPorts) {
120             logger.warn(LOG_MULTIPLE_SERVICE_INSTANCE_DIFF_INTERFACES, contrailServiceTemplateResourceId);
121             return;
122         }
123         addNetworkLinkRequirements(substitutedNodeType, numberOfPorts);
124         NodeTemplate substitutedNodeTemplate = createSubstitutedNodeTemplate(translateTo,
125                 contrailServiceTemplateResource, contrailStId, numberOfPorts);
126         String computeNodeTypeId = new ContrailTranslationHelper()
127                 .getComputeNodeTypeId(contrailServiceTemplateResource, contrailServiceTemplateResourceId,
128                         contrailServiceTemplateTranslatedId.get(), translateTo.getContext());
129         boolean orderedInterfaces = getOrderedInterfaces(contrailServiceTemplateResource);
130         ServiceTemplate nestedServiceTemplate = createNestedServiceTemplate(translateTo, computeNodeTypeId,
131                 contrailStId, substitutedNodeTemplate, orderedInterfaces);
132         addAbstractSubstitutionProperty(translateTo, substitutedNodeTemplate.getProperties(),
133                 nestedServiceTemplate, contrailServiceTemplateResource);
134         translateTo.getContext().getTranslatedServiceTemplates().put(new ContrailTranslationHelper()
135                 .getSubstitutionContrailServiceTemplateMetadata(translateTo.getHeatFileName(),
136                         translateTo.getTranslatedId()), nestedServiceTemplate);
137     }
138
139     private void addAbstractSubstitutionProperty(TranslateTo translateTo,
140                                                  Map<String, Object> substitutionProperties,
141                                                  ServiceTemplate nestedServiceTemplate,
142                                                  Resource contrailServiceTemplateResource) {
143         Map<String, Object> innerProps = new HashMap<>();
144         innerProps.put(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME,
145                 ToscaUtil.getServiceTemplateFileName(nestedServiceTemplate));
146         Object countValue = handleScaleOutProperty(translateTo, innerProps);
147         handleServiceScalingProperty(translateTo, innerProps, contrailServiceTemplateResource);
148         boolean mandatory = false;
149         if (countValue instanceof Integer && (Integer) countValue > 0) {
150             mandatory = true;
151         }
152         if (countValue == null) {
153             mandatory = true;
154         }
155         innerProps.put(MANDATORY_PROPERTY_NAME, mandatory);
156         substitutionProperties.put(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME, innerProps);
157     }
158
159     private Object handleScaleOutProperty(TranslateTo translateTo, Map<String, Object> innerProps) {
160         Object scaleOutPropertyValue =
161                 translateTo.getResource().getProperties().get(HeatConstants.SCALE_OUT_PROPERTY_NAME);
162         Object countValue = null;
163         if (scaleOutPropertyValue instanceof Map) {
164             countValue = TranslatorHeatToToscaPropertyConverter
165                     .getToscaPropertyValue(translateTo.getServiceTemplate(), translateTo.getTranslatedId(),
166                             Constants.MAX_INSTANCES_PROPERTY_NAME,
167                             ((Map) scaleOutPropertyValue).get(Constants.MAX_INSTANCES_PROPERTY_NAME), null,
168                             translateTo.getHeatFileName(), translateTo.getHeatOrchestrationTemplate(), null,
169                             translateTo.getContext());
170             if (countValue != null) {
171                 innerProps.put(ToscaConstants.COUNT_PROPERTY_NAME, countValue);
172             } else {
173                 innerProps.put(ToscaConstants.COUNT_PROPERTY_NAME, 1);
174             }
175         } else {
176             innerProps.put(ToscaConstants.COUNT_PROPERTY_NAME, 1);
177         }
178         return countValue;
179     }
180
181     private void handleServiceScalingProperty(TranslateTo translateTo, Map<String, Object> innerProps,
182                                               Resource contrailServiceTemplateResource) {
183         Object serviceScalingPropertyValue = contrailServiceTemplateResource.getProperties()
184                 .get(HeatConstants.SERVICE_SCALING_PROPERTY_NAME);
185         Object serviceScalingValue;
186         if (serviceScalingPropertyValue != null) {
187             serviceScalingValue = TranslatorHeatToToscaPropertyConverter
188                     .getToscaPropertyValue(translateTo.getServiceTemplate(), translateTo.getTranslatedId(),
189                             HeatConstants.SERVICE_SCALING_PROPERTY_NAME, serviceScalingPropertyValue, null,
190                             translateTo.getHeatFileName(), translateTo.getHeatOrchestrationTemplate(), null,
191                             translateTo.getContext());
192             if (serviceScalingValue != null) {
193                 innerProps.put(ToscaConstants.SCALING_ENABLED_PROPERTY_NAME,
194                         (HeatBoolean.isValueBoolean(serviceScalingValue)) ? HeatBoolean.eval(serviceScalingValue) :
195                                 serviceScalingValue);
196             }
197         }
198     }
199
200     private boolean getOrderedInterfaces(Resource contrailServiceTemplate) {
201         Object orderedInterfaces = contrailServiceTemplate.getProperties().get("ordered_interfaces");
202         if (orderedInterfaces == null) {
203             return false;
204         }
205         if (orderedInterfaces instanceof String) {
206             return HeatBoolean.eval(orderedInterfaces);
207         }
208         //if get_param, set default value to true
209         return true;
210     }
211
212     private ServiceTemplate createNestedServiceTemplate(TranslateTo translateTo,
213                                                         String computeNodeTypeId,
214                                                         String substitutedNodeTypeId,
215                                                         NodeTemplate substitutedNodeTemplate,
216                                                         boolean orderedInterfaces) {
217         ServiceTemplate nestedSubstitutionServiceTemplate = new ServiceTemplate();
218         setNestedServiceTemplateGeneralDetails(translateTo, nestedSubstitutionServiceTemplate);
219         String heatStackGroupKey = addHeatStackGroup(translateTo, nestedSubstitutionServiceTemplate);
220         addSubstitutionMappingEntry(nestedSubstitutionServiceTemplate, substitutedNodeTypeId);
221         handleInputParameters(nestedSubstitutionServiceTemplate, translateTo);
222         String computeNodeTemplateId = handleComputeNodeTemplate(translateTo, computeNodeTypeId,
223                 nestedSubstitutionServiceTemplate, heatStackGroupKey);
224         handleOutputParameters(nestedSubstitutionServiceTemplate, computeNodeTemplateId, translateTo);
225         handleServiceInstanceInterfaces(translateTo,
226                 new ContrailServiceInstanceTo(nestedSubstitutionServiceTemplate, substitutedNodeTemplate,
227                         heatStackGroupKey, orderedInterfaces, computeNodeTemplateId));
228         return nestedSubstitutionServiceTemplate;
229     }
230
231     private void handleOutputParameters(ServiceTemplate nestedSubstitutionServiceTemplate,
232                                         String nodeTemplateId, TranslateTo translateTo) {
233         if (nodeTemplateId == null) {
234             return;
235         }
236         ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
237
238         Optional<NodeType> contrailAbstractNodeType =
239                 toscaAnalyzerService.fetchNodeType(ToscaNodeType.CONTRAIL_ABSTRACT_SUBSTITUTE, translateTo
240                         .getContext().getGlobalServiceTemplates().values());
241
242         if (!contrailAbstractNodeType.isPresent()) {
243             return;
244         }
245         Map<String, AttributeDefinition> contrailAbstractAttributes =
246                 contrailAbstractNodeType.get().getAttributes();
247         Map<String, ParameterDefinition> nestedSubstitutionServiceTemplateOutputs = new HashMap<>();
248
249         if (contrailAbstractAttributes == null) {
250             return;
251         }
252
253         for (Map.Entry<String, AttributeDefinition> attributeDefinitionEntry : contrailAbstractAttributes.entrySet()) {
254             AttributeDefinition abstractAttributeDef = attributeDefinitionEntry.getValue();
255             if (abstractAttributeDef != null) {
256                 Map<String, List> outputValue = new HashMap<>();
257                 List<String> outputGetAttributeList = new ArrayList<>();
258                 outputGetAttributeList.add(nodeTemplateId);
259                 outputGetAttributeList.add(attributeDefinitionEntry.getKey());
260                 outputValue.put(ToscaFunctions.GET_ATTRIBUTE.getFunctionName(), outputGetAttributeList);
261                 nestedSubstitutionServiceTemplateOutputs.put(attributeDefinitionEntry.getKey(),
262                         DataModelUtil.convertAttributeDefToParameterDef(abstractAttributeDef, outputValue));
263             }
264         }
265
266         if (!nestedSubstitutionServiceTemplateOutputs.isEmpty()) {
267             nestedSubstitutionServiceTemplate.getTopology_template()
268                     .setOutputs(nestedSubstitutionServiceTemplateOutputs);
269         }
270     }
271
272     private void handleServiceInstanceInterfaces(TranslateTo translateTo,
273                                                  ContrailServiceInstanceTo contrailServiceInstanceTo) {
274         Resource serviceInstanceResource = translateTo.getResource();
275         Object interfaceListProperty =
276                 serviceInstanceResource.getProperties().get(HeatConstants.INTERFACE_LIST_PROPERTY_NAME);
277         if (interfaceListProperty == null) {
278             return;
279         }
280         if (interfaceListProperty instanceof List) {
281             for (int index = 0; index < ((List) interfaceListProperty).size(); index++) {
282                 Object interfaceEntry = ((List) interfaceListProperty).get(index);
283                 handleInterface(translateTo, interfaceEntry, index, contrailServiceInstanceTo);
284             }
285         } else if (interfaceListProperty instanceof Map) {
286             handleInterface(translateTo, interfaceListProperty, null, contrailServiceInstanceTo);
287         }
288     }
289
290     private void handleInterface(TranslateTo translateTo, Object interfacePropertyValue,
291                                  Integer index, ContrailServiceInstanceTo contrailServiceInstanceTo) {
292         if (index == null) {
293             index = 0;
294         }
295         NodeTemplate portNodeTemplate = createPortNodeTemplate(index, contrailServiceInstanceTo.isOrderedInterfaces(),
296                         contrailServiceInstanceTo.getComputeNodeTemplateId());
297         String portNodeTemplateId = Constants.SERVICE_INSTANCE_PORT_PREFIX + index;
298         String portReqMappingKey = Constants.SERVICE_INSTANCE_LINK_PREFIX + portNodeTemplateId;
299
300         DataModelUtil.addNodeTemplate(contrailServiceInstanceTo.getNestedSubstitutionServiceTemplate(),
301                 portNodeTemplateId, portNodeTemplate);
302         updateSubstitutionMappingRequirement(contrailServiceInstanceTo.getNestedSubstitutionServiceTemplate(),
303                 portReqMappingKey, portNodeTemplateId);
304         updateHeatStackGroup(contrailServiceInstanceTo.getNestedSubstitutionServiceTemplate(),
305                 contrailServiceInstanceTo.getHeatStackGroupKey(), portNodeTemplateId);
306         connectPortToNetwork(translateTo, interfacePropertyValue, contrailServiceInstanceTo
307                         .getSubstitutedNodeTemplate(), portReqMappingKey);
308     }
309
310     private void connectPortToNetwork(TranslateTo translateTo, Object interfacePropertyValue,
311                                       NodeTemplate substitutedNodeTemplate,
312                                       String portReqMappingKey) {
313         List<String> validNetworksForConnections = ImmutableList.of(
314                 HeatResourcesTypes.NEUTRON_NET_RESOURCE_TYPE.getHeatResource(),
315                 HeatResourcesTypes.CONTRAIL_VIRTUAL_NETWORK_RESOURCE_TYPE.getHeatResource());
316         if (!(interfacePropertyValue instanceof Map)) {
317             return;
318         }
319         Object virtualNetworkValue = ((Map) interfacePropertyValue).get(HeatConstants.VIRTUAL_NETWORK_PROPERTY_NAME);
320         if (virtualNetworkValue == null) {
321             logger.warn(LOG_MISSING_VIRTUAL_NETWORK_INTERFACE_LIST, translateTo.getResourceId(),
322                     translateTo.getResource().getType());
323             return;
324         }
325         Optional<AttachedResourceId> networkAttachedResourceId = HeatToToscaUtil
326                 .extractAttachedResourceId(translateTo.getHeatFileName(), translateTo.getHeatOrchestrationTemplate(),
327                         translateTo.getContext(), virtualNetworkValue);
328         if (!networkAttachedResourceId.isPresent()) {
329             return;
330         }
331         Optional<String> networkResourceId =
332                 HeatToToscaUtil.getContrailAttachedHeatResourceId(networkAttachedResourceId.get());
333         if (networkResourceId.isPresent()) {
334             Resource networkResource = HeatToToscaUtil.getResource(translateTo.getHeatOrchestrationTemplate(),
335                     networkResourceId.get(), translateTo.getHeatFileName());
336             if (validNetworksForConnections.contains(networkResource.getType())) {
337                 Optional<String> networkTranslatedId =
338                         getResourceTranslatedId(translateTo.getHeatFileName(),
339                                 translateTo.getHeatOrchestrationTemplate(), networkResourceId.get(),
340                                 translateTo.getContext());
341                 networkTranslatedId.ifPresent(translatedId -> addLinkToNetworkRequirementAssignment(
342                                         substitutedNodeTemplate, translatedId, portReqMappingKey));
343
344             } else {
345                 logger.warn(LOG_UNSUPPORTED_NETWORK_RESOURCE_CONNECTION, translateTo.getResourceId(),
346                         translateTo.getResource().getType());
347             }
348         } else if (networkAttachedResourceId.get().isGetParam()
349                 && networkAttachedResourceId.get().getEntityId() instanceof String) {
350             TranslatedHeatResource translatedSharedResourceId = translateTo.getContext().getHeatSharedResourcesByParam()
351                             .get(networkAttachedResourceId.get().getEntityId());
352             if (Objects.nonNull(translatedSharedResourceId)
353                     && !HeatToToscaUtil.isHeatFileNested(translateTo, translateTo.getHeatFileName())) {
354                 addLinkToNetworkRequirementAssignment(substitutedNodeTemplate,
355                         translatedSharedResourceId.getTranslatedId(), portReqMappingKey);
356             }
357         } else {
358             logger.warn(LOG_INVALID_NETWORK_CONNECTION, translateTo.getResourceId(),
359                     translateTo.getResource().getType(), virtualNetworkValue.toString());
360         }
361     }
362
363     private NodeTemplate createPortNodeTemplate(Integer index, boolean orderedInterfaces,
364                                                 String computeNodeTemplateId) {
365         NodeTemplate portNodeTemplate = new NodeTemplate();
366         portNodeTemplate.setType(ToscaNodeType.CONTRAIL_PORT);
367         Map<String, Object> portProperties = new HashMap<>();
368         portProperties.put("static_routes", DataModelUtil
369                 .createGetInputPropertyValueFromListParameter(INTERFACE_LIST, index, "static_routes"));
370         portProperties.put("virtual_network", DataModelUtil
371                 .createGetInputPropertyValueFromListParameter(INTERFACE_LIST, index, "virtual_network"));
372         portProperties.put("allowed_address_pairs", DataModelUtil
373                 .createGetInputPropertyValueFromListParameter(INTERFACE_LIST, index,
374                         "allowed_address_pairs"));
375         portProperties.put("ip_address", DataModelUtil
376                 .createGetInputPropertyValueFromListParameter(INTERFACE_LIST, index, "ip_address"));
377         portProperties.put("static_route",
378                 DataModelUtil.createGetInputPropertyValueFromListParameter("static_routes_list", index));
379         portProperties.put("shared_ip",
380                 DataModelUtil.createGetInputPropertyValueFromListParameter("shared_ip_list", index));
381         portProperties.put("interface_type", DataModelUtil
382                 .createGetInputPropertyValueFromListParameter("service_interface_type_list", index));
383         if (orderedInterfaces) {
384             portProperties.put("order", index);
385         }
386         portNodeTemplate.setProperties(portProperties);
387         DataModelUtil.addBindingReqFromPortToCompute(computeNodeTemplateId, portNodeTemplate);
388         return portNodeTemplate;
389     }
390
391
392     private void addLinkToNetworkRequirementAssignment(NodeTemplate nodeTemplate,
393                                                        String connectedNodeTranslatedId,
394                                                        String requirementId) {
395         if (nodeTemplate == null || connectedNodeTranslatedId == null) {
396             return;
397         }
398         RequirementAssignment requirement = new RequirementAssignment();
399         requirement.setCapability(ToscaCapabilityType.NATIVE_NETWORK_LINKABLE);
400         requirement.setRelationship(ToscaRelationshipType.NATIVE_NETWORK_LINK_TO);
401         requirement.setNode(connectedNodeTranslatedId);
402         DataModelUtil.addRequirementAssignment(nodeTemplate, requirementId, requirement);
403     }
404
405     private void updateHeatStackGroup(ServiceTemplate serviceTemplate, String heatStackGroupKey,
406                                       String memberId) {
407         serviceTemplate.getTopology_template().getGroups().get(heatStackGroupKey).getMembers().add(memberId);
408     }
409
410     private void updateSubstitutionMappingRequirement(ServiceTemplate serviceTemplate,
411                                                       String portReqMappingKey,
412                                                       String portNodeTemplateId) {
413         List<String> portReqMappingValue = new ArrayList<>();
414         portReqMappingValue.add(portNodeTemplateId);
415         portReqMappingValue.add(ToscaConstants.LINK_REQUIREMENT_ID);
416         DataModelUtil.addSubstitutionMappingReq(serviceTemplate, portReqMappingKey, portReqMappingValue);
417     }
418
419     private void addSubstitutionMappingEntry(ServiceTemplate nestedSubstitutionServiceTemplate,
420                                              String substitutedNodeTypeId) {
421         SubstitutionMapping substitutionMappings = new SubstitutionMapping();
422         substitutionMappings.setNode_type(substitutedNodeTypeId);
423         DataModelUtil.addSubstitutionMapping(nestedSubstitutionServiceTemplate, substitutionMappings);
424     }
425
426     private void handleInputParameters(ServiceTemplate nestedSubstitutionServiceTemplate,
427                                        TranslateTo translateTo) {
428         ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
429         Optional<NodeType> contrailAbstractNodeType = toscaAnalyzerService.fetchNodeType(ToscaNodeType
430                 .CONTRAIL_ABSTRACT_SUBSTITUTE, translateTo.getContext().getGlobalServiceTemplates().values());
431         Map<String, ParameterDefinition> nestedSubstitutionServiceTemplateInputs = new HashMap<>();
432         if (contrailAbstractNodeType.isPresent()) {
433             Map<String, PropertyDefinition> contrailAbstractProperties = contrailAbstractNodeType.get().getProperties();
434             for (Map.Entry<String, PropertyDefinition> propertyEntry : contrailAbstractProperties.entrySet()) {
435                 PropertyDefinition abstractPropertyDef = contrailAbstractProperties.get(propertyEntry.getKey());
436                 if (abstractPropertyDef != null) {
437                     nestedSubstitutionServiceTemplateInputs.put(propertyEntry.getKey(),
438                             DataModelUtil.convertPropertyDefToParameterDef(abstractPropertyDef));
439                 }
440             }
441         }
442         if (!nestedSubstitutionServiceTemplateInputs.isEmpty()) {
443             nestedSubstitutionServiceTemplate.getTopology_template().setInputs(nestedSubstitutionServiceTemplateInputs);
444         }
445     }
446
447     private String handleComputeNodeTemplate(TranslateTo translateTo, String computeNodeTypeId,
448                                              ServiceTemplate nestedSubstitutionServiceTemplate,
449                                              String heatStackGroupKey) {
450         ToscaAnalyzerService toscaAnalyzerService = new ToscaAnalyzerServiceImpl();
451         Optional<NodeType> contrailComputeNodeType = toscaAnalyzerService.fetchNodeType(ToscaNodeType.CONTRAIL_COMPUTE,
452                         translateTo.getContext().getGlobalServiceTemplates().values());
453         Map<String, Object> computeNodeTemplateProperties = null;
454         if (contrailComputeNodeType.isPresent()) {
455             Map<String, PropertyDefinition> contrailComputeProperties = contrailComputeNodeType.get().getProperties();
456             computeNodeTemplateProperties = new HashMap<>();
457             if (contrailComputeProperties != null) {
458                 for (String computePropertyKey : contrailComputeProperties.keySet()) {
459                     Map<String, Object> getInputProperty = new HashMap<>();
460                     getInputProperty.put(ToscaFunctions.GET_INPUT.getFunctionName(), computePropertyKey);
461                     computeNodeTemplateProperties.put(computePropertyKey, getInputProperty);
462                 }
463             }
464         }
465
466         NodeTemplate computeNodeTemplate = new NodeTemplate();
467         computeNodeTemplate.setType(computeNodeTypeId);
468         if (computeNodeTemplateProperties != null && !computeNodeTemplateProperties.isEmpty()) {
469             computeNodeTemplate.setProperties(computeNodeTemplateProperties);
470         }
471         String computeNodeTemplateId = translateTo.getTranslatedId();
472         DataModelUtil.addNodeTemplate(nestedSubstitutionServiceTemplate, computeNodeTemplateId, computeNodeTemplate);
473         nestedSubstitutionServiceTemplate.getTopology_template().getGroups().get(heatStackGroupKey)
474                 .getMembers().add(computeNodeTemplateId);
475         return computeNodeTemplateId;
476     }
477
478     private String addHeatStackGroup(TranslateTo translateTo, ServiceTemplate serviceTemplate) {
479         GroupDefinition serviceInstanceGroupDefinition = new GroupDefinition();
480         serviceInstanceGroupDefinition.setType(ToscaGroupType.HEAT_STACK);
481         Map<String, Object> groupProperties = new HashMap<>();
482         groupProperties.put("heat_file",
483                 "../" + (new ToscaFileOutputServiceCsarImpl()).getArtifactsFolderName() + "/"
484                         + translateTo.getHeatFileName());
485         serviceInstanceGroupDefinition.setProperties(groupProperties);
486         serviceInstanceGroupDefinition.setMembers(new ArrayList<>());
487         String heatStackGroupKey = translateTo.getTranslatedId() + "_group";
488         DataModelUtil.addGroupDefinitionToTopologyTemplate(serviceTemplate, heatStackGroupKey,
489                 serviceInstanceGroupDefinition);
490         return heatStackGroupKey;
491     }
492
493
494     private void setNestedServiceTemplateGeneralDetails(TranslateTo translateTo,
495                                                         ServiceTemplate
496                                                                 nestedSubstitutionServiceTemplate) {
497         Map<String, String> nestedTemplateMetadata = new HashMap<>();
498         String nestedTemplateName = new ContrailTranslationHelper()
499                 .getSubstitutionContrailServiceTemplateMetadata(translateTo.getHeatFileName(),
500                         translateTo.getResourceId());
501         nestedTemplateMetadata.put(ToscaConstants.ST_METADATA_TEMPLATE_NAME, nestedTemplateName);
502         nestedSubstitutionServiceTemplate.setMetadata(nestedTemplateMetadata);
503         nestedSubstitutionServiceTemplate.setTosca_definitions_version(ToscaConstants.TOSCA_DEFINITIONS_VERSION);
504         nestedSubstitutionServiceTemplate.setTopology_template(new TopologyTemplate());
505         List<Map<String, Import>> globalTypesImportList = GlobalTypesGenerator.getGlobalTypesImportList();
506         globalTypesImportList.addAll(
507                 HeatToToscaUtil.createImportList(Constants.GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME));
508         nestedSubstitutionServiceTemplate.setImports(globalTypesImportList);
509     }
510
511     private NodeTemplate createSubstitutedNodeTemplate(TranslateTo translateTo,
512                                                        Resource contrailServiceTemplateResource,
513                                                        String contrailServiceTemplateTranslatedId,
514                                                        int numberOfPorts) {
515         boolean isImportAddedToServiceTemplate =
516                 DataModelUtil
517                         .isImportAddedToServiceTemplate(translateTo.getServiceTemplate().getImports(), Constants
518                                 .GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME);
519         if (!isImportAddedToServiceTemplate) {
520             translateTo.getServiceTemplate().getImports()
521                     .addAll(HeatToToscaUtil
522                             .createImportList(Constants.GLOBAL_SUBSTITUTION_TYPES_TEMPLATE_NAME));
523         }
524         NodeTemplate substitutesNodeTemplate = new NodeTemplate();
525         substitutesNodeTemplate.setType(contrailServiceTemplateTranslatedId);
526         List<String> directiveList = new ArrayList<>();
527         directiveList.add(ToscaConstants.NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
528         substitutesNodeTemplate.setDirectives(directiveList);
529         substitutesNodeTemplate.setProperties(TranslatorHeatToToscaPropertyConverter
530                 .getToscaPropertiesSimpleConversion(translateTo.getServiceTemplate(),
531                         translateTo.getResourceId(), translateTo.getResource().getProperties(),
532                         substitutesNodeTemplate.getProperties(), translateTo.getHeatFileName(),
533                         translateTo.getHeatOrchestrationTemplate(),
534                         HeatResourcesTypes.CONTRAIL_SERVICE_INSTANCE.getHeatResource(), substitutesNodeTemplate,
535                         translateTo.getContext()));
536         substitutesNodeTemplate.setProperties(TranslatorHeatToToscaPropertyConverter
537                 .getToscaPropertiesSimpleConversion(translateTo.getServiceTemplate(),
538                         translateTo.getResourceId(), contrailServiceTemplateResource.getProperties(),
539                         substitutesNodeTemplate.getProperties(), translateTo.getHeatFileName(),
540                         translateTo.getHeatOrchestrationTemplate(),
541                         HeatResourcesTypes.CONTRAIL_SERVICE_TEMPLATE.getHeatResource(), substitutesNodeTemplate,
542                         translateTo.getContext()));
543         HeatToToscaUtil.mapBoolean(substitutesNodeTemplate, HeatToToscaUtil
544                 .getToscaPropertyName(translateTo.getContext(), contrailServiceTemplateResource.getType(),
545                         HeatConstants.AVAILABILITY_ZONE_ENABLE_PROPERTY_NAME));
546         HeatToToscaUtil.mapBoolean(substitutesNodeTemplate, HeatToToscaUtil
547                 .getToscaPropertyName(translateTo.getContext(), contrailServiceTemplateResource.getType(),
548                         HeatConstants.ORDERED_INTERFACES_PROPERTY_NAME));
549
550         Object sharedIpListPropertyValue =
551                 contrailServiceTemplateResource.getProperties()
552                         .get(HeatConstants.SHARED_IP_LIST_PROPERTY_NAME);
553         String toscaSharedIpListPropertyName = HeatToToscaUtil
554                 .getToscaPropertyName(translateTo.getContext(), contrailServiceTemplateResource.getType(),
555                         HeatConstants.SHARED_IP_LIST_PROPERTY_NAME);
556         Optional<List<Map<String, List>>> sharedIpTranslatedSplitFun =
557                 new ContrailTranslationHelper()
558                         .translateFnSplitFunction(sharedIpListPropertyValue, numberOfPorts, true);
559         if (sharedIpTranslatedSplitFun.isPresent()) {
560             substitutesNodeTemplate.getProperties()
561                     .put(toscaSharedIpListPropertyName, sharedIpTranslatedSplitFun.get());
562         } else {
563             HeatToToscaUtil.mapBooleanList(substitutesNodeTemplate, toscaSharedIpListPropertyName);
564         }
565
566         Object staticRouteListPropertyValue =
567                 contrailServiceTemplateResource.getProperties()
568                         .get(HeatConstants.STATIC_ROUTES_LIST_PROPERTY_NAME);
569         String toscaStaticRoutesListPropertyName = HeatToToscaUtil
570                 .getToscaPropertyName(translateTo.getContext(), contrailServiceTemplateResource.getType(),
571                         HeatConstants.STATIC_ROUTES_LIST_PROPERTY_NAME);
572         Optional<List<Map<String, List>>> staticRouteTranslatedSplitFun =
573                 new ContrailTranslationHelper()
574                         .translateFnSplitFunction(staticRouteListPropertyValue, numberOfPorts, true);
575         if (staticRouteTranslatedSplitFun.isPresent()) {
576             substitutesNodeTemplate.getProperties()
577                     .put(toscaStaticRoutesListPropertyName, staticRouteTranslatedSplitFun.get());
578         } else {
579             HeatToToscaUtil.mapBooleanList(substitutesNodeTemplate, toscaStaticRoutesListPropertyName);
580         }
581
582         Object serviceInterfaceTypeListPropertyValue =
583                 contrailServiceTemplateResource.getProperties()
584                         .get(HeatConstants.SERVICE_INTERFCAE_TYPE_LIST_PROPERTY_NAME);
585         String toscaServiceInterfaceTypeListPropertyName = HeatToToscaUtil
586                 .getToscaPropertyName(translateTo.getContext(), contrailServiceTemplateResource.getType(),
587                         HeatConstants.SERVICE_INTERFCAE_TYPE_LIST_PROPERTY_NAME);
588         Optional<List<Map<String, List>>> serviceInterfaceTypeTranslatedSplitFun =
589                 new ContrailTranslationHelper()
590                         .translateFnSplitFunction(serviceInterfaceTypeListPropertyValue, numberOfPorts, false);
591         serviceInterfaceTypeTranslatedSplitFun
592                 .ifPresent(translatedSplitFun -> substitutesNodeTemplate.getProperties()
593                         .put(toscaServiceInterfaceTypeListPropertyName, translatedSplitFun));
594
595         String substitutedNodeTemplateId = translateTo.getTranslatedId();
596         DataModelUtil.addNodeTemplate(translateTo.getServiceTemplate(), substitutedNodeTemplateId,
597                 substitutesNodeTemplate);
598         return substitutesNodeTemplate;
599     }
600
601     private void addNetworkLinkRequirements(NodeType nodeType, int numberOfPorts) {
602         if (nodeType.getRequirements() == null) {
603             List<Map<String, RequirementDefinition>> requirementList = new ArrayList<>();
604             for (int i = 0; i < numberOfPorts; i++) {
605                 Map<String, RequirementDefinition> requirementDefinitionMap = new HashMap<>();
606                 requirementDefinitionMap.put(ToscaConstants.LINK_REQUIREMENT_ID + "_port_" + i,
607                         DataModelUtil.createRequirement(ToscaCapabilityType.NATIVE_NETWORK_LINKABLE,
608                                 ToscaNodeType.NATIVE_ROOT,
609                                 ToscaRelationshipType.NATIVE_NETWORK_LINK_TO, null));
610                 requirementList.add(requirementDefinitionMap);
611             }
612             if (numberOfPorts > 0) {
613                 nodeType.setRequirements(requirementList);
614             }
615         }
616     }
617
618     private int getServiceInstanceNumberOfPorts(Resource serviceInstanceResource) {
619         int numberOfPorts;
620         Object interfaceTypeProperty =
621                 serviceInstanceResource.getProperties().get(HeatConstants.INTERFACE_LIST_PROPERTY_NAME);
622         if (interfaceTypeProperty == null) {
623             numberOfPorts = 0;
624         } else if (interfaceTypeProperty instanceof List) {
625             numberOfPorts = ((List) interfaceTypeProperty).size();
626         } else if (interfaceTypeProperty instanceof Map) {
627             numberOfPorts = 1;
628         } else {
629             numberOfPorts = 0;
630         }
631         return numberOfPorts;
632     }
633
634     private AttachedResourceId getServiceTemplateAttachedId(TranslateTo translateTo,
635                                                             Resource serviceInstanceResource) {
636         Object serviceTemplateProperty =
637                 serviceInstanceResource.getProperties().get("service_template");
638         Optional<AttachedResourceId> serviceTemplateId = HeatToToscaUtil
639                 .extractAttachedResourceId(translateTo.getHeatFileName(),
640                         translateTo.getHeatOrchestrationTemplate(), translateTo.getContext(),
641                         serviceTemplateProperty);
642         if (serviceTemplateId.isPresent()) {
643             return serviceTemplateId.get();
644         } else {
645             throw new CoreException(new MissingMandatoryPropertyErrorBuilder("service_template").build());
646         }
647     }
648
649
650 }