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