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