Toggle
[sdc.git] / openecomp-be / lib / openecomp-sdc-translator-lib / openecomp-sdc-translator-core / src / main / java / org / openecomp / sdc / translator / services / heattotosca / impl / resourcetranslation / ResourceTranslationNovaServerImpl.java
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.heat.services.HeatConstants.SNAPSHOT_ID_PROPERTY_NAME;
20 import static org.openecomp.sdc.heat.services.HeatConstants.VOL_ID_PROPERTY_NAME;
21
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Objects;
29 import java.util.Optional;
30
31 import org.apache.commons.collections4.CollectionUtils;
32 import org.apache.commons.collections4.MapUtils;
33 import org.onap.sdc.tosca.datatypes.model.GroupDefinition;
34 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
35 import org.onap.sdc.tosca.datatypes.model.NodeType;
36 import org.onap.sdc.tosca.datatypes.model.RelationshipTemplate;
37 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
38 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
39 import org.onap.sdc.tosca.datatypes.model.CapabilityDefinition;
40 import org.openecomp.sdc.heat.datatypes.HeatBoolean;
41 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
42 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
43 import org.openecomp.sdc.heat.datatypes.model.PropertiesMapKeyTypes;
44 import org.openecomp.sdc.heat.datatypes.model.Resource;
45 import org.openecomp.sdc.heat.datatypes.model.ResourceReferenceFunctions;
46 import org.openecomp.sdc.heat.services.HeatConstants;
47 import org.openecomp.sdc.logging.api.Logger;
48 import org.openecomp.sdc.logging.api.LoggerFactory;
49 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
50 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
51 import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType;
52 import org.openecomp.sdc.tosca.services.DataModelUtil;
53 import org.openecomp.sdc.tosca.services.ToscaConstants;
54 import org.openecomp.sdc.tosca.services.ToscaUtil;
55 import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId;
56 import org.openecomp.sdc.translator.datatypes.heattotosca.PropertyRegexMatcher;
57 import org.openecomp.sdc.translator.datatypes.heattotosca.TranslationContext;
58 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo;
59 import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslatedHeatResource;
60 import org.openecomp.sdc.translator.datatypes.heattotosca.unifiedmodel.consolidation.ComputeConsolidationDataHandler;
61 import org.openecomp.sdc.translator.services.heattotosca.ConsolidationDataUtil;
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.NameExtractor;
65 import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory;
66 import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaPropertyConverter;
67
68 public class ResourceTranslationNovaServerImpl extends ResourceTranslationBase {
69     private static final Logger logger = LoggerFactory.getLogger(ResourceTranslationNovaServerImpl.class);
70     private static final String BLOCK_DEVICE_MAPPING_DEVICE_NAME = "device_name";
71     private static final String VOL_ATTACH_DEVICE_PROPERTY_NAME = "device";
72     private static final String FABRIC_CONFIGURATION_KEY = "fabric_configuration_monitoring";
73    
74
75     @Override
76     protected void translate(TranslateTo translateTo) {
77         TranslationContext context = translateTo.getContext();
78         Map<String, Object> properties = translateTo.getResource().getProperties();
79         String heatFileName = translateTo.getHeatFileName();
80         ServiceTemplate serviceTemplate = translateTo.getServiceTemplate();
81         String nodeTypeRef = createLocalNodeType(serviceTemplate, translateTo.getResource(),
82                 translateTo.getResourceId(), translateTo.getTranslatedId());
83         String serviceTemplateFileName = ToscaUtil.getServiceTemplateFileName(serviceTemplate);
84
85         context.getComputeConsolidationDataHandler().addConsolidationData(
86                 serviceTemplateFileName, nodeTypeRef, translateTo.getTranslatedId());
87
88         NodeTemplate novaNodeTemplate = new NodeTemplate();
89         novaNodeTemplate.setType(nodeTypeRef);
90         HeatOrchestrationTemplate heatOrchestrationTemplate =
91                 translateTo.getHeatOrchestrationTemplate();
92         novaNodeTemplate.setProperties(TranslatorHeatToToscaPropertyConverter
93                 .getToscaPropertiesSimpleConversion(serviceTemplate, translateTo.getResourceId(),
94                         properties, novaNodeTemplate.getProperties(), heatFileName,
95                         heatOrchestrationTemplate, translateTo.getResource().getType(),
96                         novaNodeTemplate, context));
97         HeatToToscaUtil.mapBoolean(novaNodeTemplate, HeatToToscaUtil
98                 .getToscaPropertyName(translateTo, HeatConstants.CONFIG_DRIVE_PROPERTY_NAME));
99         manageNovaServerNetwork(translateTo, novaNodeTemplate);
100         manageNovaServerBlockDeviceMapping(translateTo, novaNodeTemplate);
101         manageNovaServerGroupMapping(translateTo, novaNodeTemplate);
102         DataModelUtil.addNodeTemplate(serviceTemplate, translateTo.getTranslatedId(), novaNodeTemplate);
103     }
104
105     private void manageNovaServerGroupMapping(TranslateTo translateTo,
106                                                      NodeTemplate novaNodeTemplate) {
107         Map properties = translateTo.getResource().getProperties();
108         if (isSchedulerHintsPropExist(properties)) {
109             Object schedulerHints = properties.get(ResourceReferenceFunctions.SCHEDULER_HINTS.getFunction());
110             if (schedulerHints instanceof Map) {
111                 addServerGroupHintsToPoliciesGroups(translateTo,
112                         novaNodeTemplate, (Map) schedulerHints);
113             } else {
114                 logger.warn("'scheduler_hints' property of resource '{}' is not valid. This property should be a map",
115                         translateTo.getResourceId());
116             }
117         }
118     }
119
120     private void addServerGroupHintsToPoliciesGroups(TranslateTo translateTo,
121                                                             NodeTemplate novaNodeTemplate,
122                                                             Map schedulerHints) {
123         for (Object hint : schedulerHints.values()) {
124             Optional<AttachedResourceId> attachedResourceId = HeatToToscaUtil
125                     .extractAttachedResourceId(translateTo.getHeatFileName(), translateTo
126                             .getHeatOrchestrationTemplate(), translateTo.getContext(), hint);
127             if (attachedResourceId.isPresent()) {
128                 AttachedResourceId serverGroupResourceId = attachedResourceId.get();
129                 Object serverGroupResourceToTranslate = serverGroupResourceId.getEntityId();
130                 if (serverGroupResourceId.isGetResource()) {
131                     addServerGroupHintGetResource(translateTo, novaNodeTemplate, serverGroupResourceToTranslate);
132                 } else if (serverGroupResourceId.isGetParam() && serverGroupResourceToTranslate instanceof String) {
133                     addServerGroupHintGetParam(translateTo, novaNodeTemplate, serverGroupResourceToTranslate);
134                 }
135             }
136         }
137     }
138
139     private void addServerGroupHintGetParam(TranslateTo translateTo, NodeTemplate novaNodeTemplate,
140                                                    Object serverGroupResourceToTranslate) {
141         TranslatedHeatResource translatedServerGroupResource = translateTo.getContext()
142                 .getHeatSharedResourcesByParam().get(serverGroupResourceToTranslate);
143         if (Objects.nonNull(translatedServerGroupResource)
144                     && !HeatToToscaUtil.isHeatFileNested(translateTo, translateTo.getHeatFileName())
145                     && isResourceTypeServerGroup(translatedServerGroupResource)) {
146             Map<String, GroupDefinition> groups =
147                     translateTo.getServiceTemplate().getTopology_template().getGroups();
148             if (MapUtils.isNotEmpty(groups) && Objects.nonNull(groups.get(translatedServerGroupResource
149                                                                                   .getTranslatedId()))) {
150                 groups.get(translatedServerGroupResource.getTranslatedId()).getMembers()
151                       .add(translateTo.getTranslatedId());
152                 //Add group Id to compute consolidation data
153                 updateComputeConsolidationDataGroup(translateTo, novaNodeTemplate,
154                         translatedServerGroupResource.getTranslatedId());
155             }
156         }
157     }
158
159     private void addServerGroupHintGetResource(TranslateTo translateTo, NodeTemplate novaNodeTemplate,
160                                                       Object serverGroupResourceToTranslate) {
161         boolean isHintOfTypeNovaServerGroup = isHintOfTypeNovaServerGroup(translateTo
162                 .getHeatOrchestrationTemplate(), serverGroupResourceToTranslate);
163         if (isHintOfTypeNovaServerGroup) {
164             addNovaServerToPolicyGroup(translateTo, (String) serverGroupResourceToTranslate, novaNodeTemplate);
165         }
166     }
167
168     private boolean isResourceTypeServerGroup(TranslatedHeatResource translatedServerGroupResource) {
169         return translatedServerGroupResource.getHeatResource().getType()
170                 .equals(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE.getHeatResource());
171     }
172
173     private void updateComputeConsolidationDataGroup(TranslateTo translateTo,
174             NodeTemplate novaNodeTemplate, String groupId) {
175         ComputeConsolidationDataHandler handler = translateTo.getContext().getComputeConsolidationDataHandler();
176         handler.addGroupIdToConsolidationData(translateTo,novaNodeTemplate.getType(),
177                 translateTo.getTranslatedId(), groupId);
178     }
179
180     private boolean isHintOfTypeNovaServerGroup(HeatOrchestrationTemplate heatOrchestrationTemplate,
181                                                        Object resourceToTranslate) {
182         return heatOrchestrationTemplate.getResources().get(resourceToTranslate).getType()
183                                         .equals(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE.getHeatResource());
184     }
185
186     private void addNovaServerToPolicyGroup(TranslateTo translateTo,
187                                                    String resourceToTranslate,
188                                                    NodeTemplate novaNodeTemplate) {
189         Resource serverGroup =
190                 HeatToToscaUtil.getResource(translateTo.getHeatOrchestrationTemplate(), resourceToTranslate,
191                         translateTo.getHeatFileName());
192         Optional<String> serverGroupTranslatedId = ResourceTranslationFactory.getInstance(serverGroup)
193                 .translateResource(translateTo.getHeatFileName(), translateTo.getServiceTemplate(),
194                         translateTo.getHeatOrchestrationTemplate(), serverGroup, resourceToTranslate,
195                         translateTo.getContext());
196         if (serverGroupTranslatedId.isPresent()) {
197             translateTo.getServiceTemplate().getTopology_template().getGroups().get(serverGroupTranslatedId.get())
198                        .getMembers().add(translateTo.getTranslatedId());
199             updateComputeConsolidationDataGroup(translateTo, novaNodeTemplate, serverGroupTranslatedId.get());
200         }
201     }
202
203     private boolean isSchedulerHintsPropExist(Map properties) {
204         return !MapUtils.isEmpty(properties)
205                        && Objects.nonNull(properties.get(ResourceReferenceFunctions.SCHEDULER_HINTS.getFunction()));
206     }
207
208     private void manageNovaServerBlockDeviceMapping(TranslateTo translateTo,
209                                                            NodeTemplate novaNodeTemplate) {
210         Resource resource = translateTo.getResource();
211         List<Map<String, Object>> blockDeviceMappingList = getBlockDeviceMappingList(resource);
212         if (CollectionUtils.isEmpty(blockDeviceMappingList)) {
213             return;
214         }
215         int index = 0;
216         for (Map<String, Object> blockDeviceMapping : blockDeviceMappingList) {
217             index = connectBlockDeviceToNovaServer(translateTo, novaNodeTemplate, index, blockDeviceMapping);
218         }
219     }
220
221     private int connectBlockDeviceToNovaServer(TranslateTo translateTo, NodeTemplate novaNodeTemplate, int index,
222                                                       Map<String, Object> blockDeviceMapping) {
223         Object volumeIdObject = blockDeviceMapping.get(VOL_ID_PROPERTY_NAME);
224         Object snapshotIdObject = blockDeviceMapping.get(SNAPSHOT_ID_PROPERTY_NAME);
225
226         if (volumeIdObject == null && snapshotIdObject == null) {
227             logger.warn("Resource '{}' has block_device_mapping property with empty/missing volume_id and snapshot_id "
228                                 + "properties. Entry number {}, this entry will be ignored in TOSCA translation.",
229                     translateTo.getResourceId(), (index + 1));
230             index++;
231             return index;
232         }
233         if (volumeIdObject == null) {
234             connectBlockDeviceUsingSnapshotId(translateTo, novaNodeTemplate, snapshotIdObject, index,
235                     blockDeviceMapping);
236         } else {
237             connectBlockDeviceUsingVolumeId(translateTo, novaNodeTemplate, volumeIdObject);
238         }
239         index++;
240         return index;
241     }
242
243     private void connectBlockDeviceUsingVolumeId(TranslateTo translateTo, NodeTemplate novaNodeTemplate,
244                                                         Object volumeIdObject) {
245         Optional<AttachedResourceId> attachedVolumeId = HeatToToscaUtil
246                 .extractAttachedResourceId(translateTo.getHeatFileName(), translateTo.getHeatOrchestrationTemplate(),
247                         translateTo.getContext(), volumeIdObject);
248         if (attachedVolumeId.isPresent() && attachedVolumeId.get().isGetResource()) {
249             connectNovaServerToVolume(novaNodeTemplate, (String) attachedVolumeId.get().getTranslatedId(), null,
250                     translateTo);
251         }
252     }
253
254     private void connectBlockDeviceUsingSnapshotId(TranslateTo translateTo, NodeTemplate novaNodeTemplate,
255                                                           Object snapshotIdObject, int index,
256                                                           Map<String, Object> blockDeviceMapping) {
257         String novaServerTranslatedId = translateTo.getTranslatedId();
258         String volumeResourceId;
259         Optional<AttachedResourceId> attachedSnapshotId = HeatToToscaUtil
260                 .extractAttachedResourceId(translateTo.getHeatFileName(), translateTo.getHeatOrchestrationTemplate(),
261                         translateTo.getContext(), snapshotIdObject);
262         if (attachedSnapshotId.isPresent()) {
263             volumeResourceId = novaServerTranslatedId + "_" + attachedSnapshotId.get().getEntityId();
264             String deviceName = (String) blockDeviceMapping.get(BLOCK_DEVICE_MAPPING_DEVICE_NAME);
265             String relationshipId = novaServerTranslatedId + "_" + index;
266             createVolumeAttachesToRelationship(translateTo.getServiceTemplate(), deviceName, novaServerTranslatedId,
267                     volumeResourceId, relationshipId);
268             createCinderVolumeNodeTemplate(translateTo, volumeResourceId, blockDeviceMapping);
269             connectNovaServerToVolume(novaNodeTemplate, volumeResourceId, relationshipId,
270                     translateTo);
271         }
272     }
273
274     private void connectNovaServerToVolume(NodeTemplate novaNodeTemplate, String volumeResourceId,
275                                                   String relationshipId, TranslateTo translateTo) {
276         RequirementAssignment requirementAssignment = new RequirementAssignment();
277         requirementAssignment.setCapability(ToscaCapabilityType.NATIVE_ATTACHMENT);
278         requirementAssignment.setNode(volumeResourceId);
279         if (relationshipId != null) {
280             requirementAssignment.setRelationship(relationshipId);
281         } else {
282             requirementAssignment
283                     .setRelationship(ToscaRelationshipType.NATIVE_ATTACHES_TO);
284         }
285         DataModelUtil.addRequirementAssignment(novaNodeTemplate, ToscaConstants.LOCAL_STORAGE_REQUIREMENT_ID,
286                 requirementAssignment);
287         //Add volume consolidation data
288         ConsolidationDataUtil.updateComputeConsolidationDataVolumes(translateTo, novaNodeTemplate.getType(),
289                 translateTo.getTranslatedId(), ToscaConstants.LOCAL_STORAGE_REQUIREMENT_ID, requirementAssignment);
290     }
291
292     private void createCinderVolumeNodeTemplate(TranslateTo translateTo,
293                                                        String volumeResourceId,
294                                                        Map<String, Object> blockDeviceMapping) {
295         NodeTemplate cinderVolumeNodeTemplate = new NodeTemplate();
296         cinderVolumeNodeTemplate.setType(ToscaNodeType.CINDER_VOLUME);
297         cinderVolumeNodeTemplate.setProperties(TranslatorHeatToToscaPropertyConverter
298                 .getToscaPropertiesSimpleConversion(translateTo.getServiceTemplate(), translateTo.getResourceId(),
299                         blockDeviceMapping, null,
300                         translateTo.getHeatFileName(), translateTo.getHeatOrchestrationTemplate(),
301                         HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource(),
302                         cinderVolumeNodeTemplate, translateTo.getContext()));
303         DataModelUtil.addNodeTemplate(translateTo.getServiceTemplate(), volumeResourceId, cinderVolumeNodeTemplate);
304     }
305
306     private void createVolumeAttachesToRelationship(ServiceTemplate serviceTemplate,
307                                                            String deviceName, String novaServerTranslatedId,
308                                                            String volumeId, String relationshipId) {
309         RelationshipTemplate relationshipTemplate = new RelationshipTemplate();
310         relationshipTemplate.setType(ToscaRelationshipType.CINDER_VOLUME_ATTACHES_TO);
311         Map<String, Object> properties = new HashMap<>();
312         properties.put(ToscaConstants.INSTANCE_UUID_PROPERTY_NAME, novaServerTranslatedId);
313         properties.put(ToscaConstants.VOL_ID_PROPERTY_NAME, volumeId);
314         if (deviceName != null) {
315             properties.put(VOL_ATTACH_DEVICE_PROPERTY_NAME, deviceName);
316         }
317         relationshipTemplate.setProperties(properties);
318         DataModelUtil.addRelationshipTemplate(serviceTemplate, relationshipId, relationshipTemplate);
319     }
320
321     private List<Map<String, Object>> getBlockDeviceMappingList(Resource resource) {
322         if (Objects.isNull(resource.getProperties())) {
323             return Collections.emptyList();
324         }
325         List<Map<String, Object>> blockDeviceMappingList =
326                 (List<Map<String, Object>>) resource.getProperties().get(HeatConstants.BLOCK_DEVICE_MAPPING);
327         List<Map<String, Object>> blockDeviceMappingV2List =
328                 (List<Map<String, Object>>) resource.getProperties().get(HeatConstants.BLOCK_DEVICE_MAPPING_V2);
329
330         if (blockDeviceMappingList != null && blockDeviceMappingV2List != null) {
331             blockDeviceMappingList.addAll(blockDeviceMappingV2List);
332         } else if (CollectionUtils.isEmpty(blockDeviceMappingList)
333                            && CollectionUtils.isEmpty(blockDeviceMappingV2List)) {
334             return Collections.emptyList();
335
336         } else {
337             blockDeviceMappingList =
338                     blockDeviceMappingList != null ? blockDeviceMappingList : blockDeviceMappingV2List;
339         }
340         return blockDeviceMappingList;
341     }
342
343     private void manageNovaServerNetwork(TranslateTo translateTo,
344                                                 NodeTemplate novaNodeTemplate) {
345         Resource resource = translateTo.getResource();
346         String translatedId = translateTo.getTranslatedId();
347
348         if (resource.getProperties() == null) {
349             return;
350         }
351         Object networks = resource.getProperties().get(PropertiesMapKeyTypes.NETWORKS.getKeyMap());
352         if (Objects.isNull(networks) || !(networks instanceof List)) {
353             return;
354         }
355
356         List<Map<String, Object>> heatNetworkList = (List<Map<String, Object>>) networks;
357         
358        
359         for (Map<String, Object> heatNetwork : heatNetworkList) {
360            
361             Optional<Resource> portResourceOp = getOrTranslatePortTemplate(translateTo, heatNetwork.get(
362                     Constants.PORT_PROPERTY_NAME), translatedId, novaNodeTemplate);   
363             portResourceOp.ifPresent(portResource -> handleFabricConfiguration(translateTo, novaNodeTemplate.getType(), portResource));
364         }
365         
366     }  
367     
368     private void handleFabricConfiguration(TranslateTo translateTo, String resourceType, Resource portResource ){ 
369        
370        Optional<Object> valueSpacesProperty = HeatToToscaUtil.getResourceProperty(portResource, HeatConstants.VALUE_SPECS_PROPERTY_NAME);
371        
372        valueSpacesProperty.filter(props -> props instanceof Map && MapUtils.isNotEmpty((Map)props)).ifPresent(valueSpecs ->{
373            if(valueSpecs instanceof Map && (isAttFabricConfigurationFlagSet((Map)valueSpecs) || isBindingProfileFabricConfigSet((Map)valueSpecs))) {
374                addFabricConfigurationCapability(translateTo, resourceType);
375            }
376            
377        });
378       
379     }
380
381     private boolean isValueFoundAndTrue(Object value) {
382         return Objects.nonNull(value) && HeatBoolean.eval(value);
383     }
384
385     private boolean isAttFabricConfigurationFlagSet(Map valueSpecs) {
386         return isValueFoundAndTrue(valueSpecs.get(HeatConstants.ATT_FABRIC_CONFIGURATION_REQUIRED));
387     }
388
389     private boolean isBindingProfileFabricConfigSet(Map valueSpecs) {
390         Object binding_profile = valueSpecs.get(HeatConstants.VALUE_SPECS_BINDING_PROFILE_PROPERTY_NAME);
391         if (Objects.nonNull(binding_profile) && binding_profile instanceof Map) {
392             return !MapUtils.isEmpty((Map)binding_profile)
393                     && isValueFoundAndTrue(((Map)binding_profile).get(HeatConstants.VALUE_SPECS_FABRIC_CONFIG_PROPERTY_NAME));
394         }
395         return false;
396     }
397     
398     private void addFabricConfigurationCapability(TranslateTo translateTo, String localType){
399         
400         ServiceTemplate serviceTemplate = translateTo.getServiceTemplate();
401         Map<String, CapabilityDefinition> mapCapabilities = new HashMap<>();
402         CapabilityDefinition fabricConfigurationCap = new CapabilityDefinition();        
403         fabricConfigurationCap.setType(ToscaCapabilityType.FABRIC_CONFIGURATION);
404         mapCapabilities.put(FABRIC_CONFIGURATION_KEY, fabricConfigurationCap);
405         DataModelUtil.addNodeTypeCapabilitiesDef (DataModelUtil.getNodeType(serviceTemplate, localType), mapCapabilities);
406         if (logger.isDebugEnabled()) {
407             logger.debug("New capability of type {} will be added to resource {}", ToscaCapabilityType.FABRIC_CONFIGURATION, translateTo.getResourceId());
408         }
409     }
410
411     private Optional<Resource> getOrTranslatePortTemplate(TranslateTo translateTo,
412                                                    Object port,
413                                                    String novaServerResourceId,
414                                                    NodeTemplate novaNodeTemplate) {
415         String heatFileName = translateTo.getHeatFileName();
416         HeatOrchestrationTemplate heatOrchestrationTemplate = translateTo.getHeatOrchestrationTemplate();
417         TranslationContext context = translateTo.getContext();
418         Optional<AttachedResourceId> attachedPortId = HeatToToscaUtil
419                 .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context, port);
420         if (!attachedPortId.isPresent() || !attachedPortId.get().isGetResource()) {
421             return Optional.empty();
422         }
423         String resourceId = (String) attachedPortId.get().getEntityId();
424         Resource portResource = HeatToToscaUtil.getResource(heatOrchestrationTemplate, resourceId, heatFileName);
425         if (!isSupportedPortResource(portResource)) {
426             logger.warn("NovaServer connect to port resource with id : {} and type : {}. This resource type is "
427                     + "not " + "supported, therefore the connection to the port is ignored. "
428                     + "Supported types are: {}, {}", resourceId, portResource.getType(),
429                     HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource(),
430                     HeatResourcesTypes.CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE.getHeatResource());
431             return Optional.empty();
432         } else if (HeatResourcesTypes.CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE
433                            .getHeatResource().equals(portResource.getType())) {
434             Map<String, Object> properties = portResource.getProperties();
435             if (!MapUtils.isEmpty(properties) && Objects.nonNull(properties.get(HeatConstants.PORT_TUPLE_REFS))) {
436                 novaNodeTemplate.getProperties().put(ToscaConstants.CONTRAIL_SERVICE_INSTANCE_IND, true);
437             }
438         }
439         ServiceTemplate serviceTemplate = translateTo.getServiceTemplate();
440         Optional<String> translatedPortId = ResourceTranslationFactory.getInstance(portResource)
441                 .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, portResource,
442                         resourceId, context);
443         if (translatedPortId.isPresent()) {
444             NodeTemplate portNodeTemplate =
445                     DataModelUtil.getNodeTemplate(serviceTemplate, translatedPortId.get());
446             DataModelUtil.addBindingReqFromPortToCompute(novaServerResourceId, portNodeTemplate);
447             // Add ports
448             ConsolidationDataUtil.updatePortInConsolidationData(translateTo, novaNodeTemplate.getType(), resourceId,
449                     portResource.getType(), translatedPortId.get());
450         } else {
451             logger.warn("NovaServer connect to port resource with id : {} and type : {}. This resource type"
452                     + " is not supported, therefore the connection to the port is ignored.", resourceId,
453                     portResource.getType());
454             return Optional.empty();
455         }
456         return Optional.ofNullable(portResource);
457     }
458
459     private boolean isSupportedPortResource(Resource portResource) {
460         return Arrays.asList(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource(),
461                 HeatResourcesTypes.CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE.getHeatResource())
462                      .contains(portResource.getType());
463     }
464
465
466     private String createLocalNodeType(ServiceTemplate serviceTemplate, Resource resource,
467                                               String resourceId, String translatedId) {
468         NameExtractor nodeTypeNameExtractor = TranslationContext.getNameExtractorImpl(resource.getType());
469         String nodeTypeName =
470                 nodeTypeNameExtractor.extractNodeTypeName(resource, resourceId, translatedId);
471
472         if (!isNodeTypeCreated(serviceTemplate, nodeTypeName)) {
473             DataModelUtil.addNodeType(serviceTemplate, nodeTypeName, createNodeType());
474         }
475         return nodeTypeName;
476     }
477
478     /**
479      * Get property Regex matcher list.
480      *
481      * @return Regex expression per nova resource property, while nova node type name is consider when
482      *      setting the name value.
483      */
484     public List<PropertyRegexMatcher> getPropertyRegexMatchersForNovaNodeType() {
485         List<PropertyRegexMatcher> propertyRegexMatchers = new ArrayList<>(3);
486         propertyRegexMatchers
487                 .add(new PropertyRegexMatcher(Constants.NAME_PROPERTY_NAME,
488                         Arrays.asList(".+_name$", ".+_names$", ".+_name_[0-9]+"), "_name"));
489         propertyRegexMatchers
490                 .add(new PropertyRegexMatcher("image", Collections.singletonList(".+_image_name$"),
491                                                      "_image_name"));
492         propertyRegexMatchers
493                 .add(new PropertyRegexMatcher("flavor", Collections.singletonList(".+_flavor_name$"),
494                                                      "_flavor_name"));
495         return propertyRegexMatchers;
496     }
497
498     private boolean isNodeTypeCreated(ServiceTemplate serviceTemplate, String nodeTypeName) {
499         return !MapUtils.isEmpty(serviceTemplate.getNode_types())
500                        && Objects.nonNull(serviceTemplate.getNode_types().get(nodeTypeName));
501     }
502
503     private NodeType createNodeType() {
504         NodeType nodeType = new NodeType();
505         nodeType.setDerived_from(ToscaNodeType.NOVA_SERVER);
506         return nodeType;
507     }
508 }