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