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