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