diff options
Diffstat (limited to 'openecomp-be/lib/openecomp-sdc-translator-lib/openecomp-sdc-translator-core/src/main/java/org/openecomp/sdc/translator/services/heattotosca/impl/ResourceTranslationNovaServerImpl.java')
-rw-r--r-- | openecomp-be/lib/openecomp-sdc-translator-lib/openecomp-sdc-translator-core/src/main/java/org/openecomp/sdc/translator/services/heattotosca/impl/ResourceTranslationNovaServerImpl.java | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/openecomp-be/lib/openecomp-sdc-translator-lib/openecomp-sdc-translator-core/src/main/java/org/openecomp/sdc/translator/services/heattotosca/impl/ResourceTranslationNovaServerImpl.java b/openecomp-be/lib/openecomp-sdc-translator-lib/openecomp-sdc-translator-core/src/main/java/org/openecomp/sdc/translator/services/heattotosca/impl/ResourceTranslationNovaServerImpl.java new file mode 100644 index 0000000000..59e0691b2b --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-translator-lib/openecomp-sdc-translator-core/src/main/java/org/openecomp/sdc/translator/services/heattotosca/impl/ResourceTranslationNovaServerImpl.java @@ -0,0 +1,419 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.translator.services.heattotosca.impl; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate; +import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes; +import org.openecomp.sdc.heat.datatypes.model.Resource; +import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType; +import org.openecomp.sdc.tosca.datatypes.ToscaNodeType; +import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType; +import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate; +import org.openecomp.sdc.tosca.datatypes.model.NodeType; +import org.openecomp.sdc.tosca.datatypes.model.RelationshipTemplate; +import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment; +import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate; +import org.openecomp.sdc.tosca.services.DataModelUtil; +import org.openecomp.sdc.tosca.services.ToscaConstants; +import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId; +import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo; +import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslatedHeatResource; +import org.openecomp.sdc.translator.services.heattotosca.Constants; +import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil; +import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory; +import org.openecomp.sdc.translator.services.heattotosca.TranslationContext; +import org.openecomp.sdc.translator.services.heattotosca.helper.NameExtractorService; +import org.openecomp.sdc.translator.services.heattotosca.helper.PropertyRegexMatcher; +import org.openecomp.sdc.translator.services.heattotosca.helper.impl.NameExtractorServiceImpl; +import org.openecomp.sdc.translator.services.heattotosca.mapping.TranslatorHeatToToscaPropertyConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public class ResourceTranslationNovaServerImpl extends ResourceTranslationBase { + protected static Logger logger = LoggerFactory.getLogger(ResourceTranslationNovaServerImpl.class); + + @Override + protected void translate(TranslateTo translateTo) { + TranslationContext context = translateTo.getContext(); + Map<String, Object> properties = translateTo.getResource().getProperties(); + String heatFileName = translateTo.getHeatFileName(); + + ServiceTemplate serviceTemplate = translateTo.getServiceTemplate(); + + String nodeTypeRef = + createLocalNodeType(serviceTemplate, translateTo.getResource().getProperties(), + translateTo.getTranslatedId()); + + NodeTemplate novaNodeTemplate = new NodeTemplate(); + novaNodeTemplate.setType(nodeTypeRef); + HeatOrchestrationTemplate heatOrchestrationTemplate = + translateTo.getHeatOrchestrationTemplate(); + novaNodeTemplate.setProperties(TranslatorHeatToToscaPropertyConverter + .getToscaPropertiesSimpleConversion(properties, novaNodeTemplate.getProperties(), + heatFileName, heatOrchestrationTemplate, translateTo.getResource().getType(), + novaNodeTemplate, context)); + + manageNovaServerNetwork(heatFileName, serviceTemplate, heatOrchestrationTemplate, + translateTo.getResource(), translateTo.getTranslatedId(), context, novaNodeTemplate); + manageNovaServerBlockDeviceMapping(heatFileName, serviceTemplate, novaNodeTemplate, + heatOrchestrationTemplate, translateTo.getResource(), translateTo.getResourceId(), + translateTo.getTranslatedId(), context); + + manageNovaServerGroupMapping(translateTo, context, properties, heatFileName, serviceTemplate, + heatOrchestrationTemplate); + DataModelUtil.addNodeTemplate(serviceTemplate, translateTo.getTranslatedId(), novaNodeTemplate); + } + + private void manageNovaServerGroupMapping(TranslateTo translateTo, TranslationContext context, + Map<String, Object> properties, String heatFileName, + ServiceTemplate serviceTemplate, + HeatOrchestrationTemplate heatOrchestrationTemplate) { + if (isSchedulerHintsPropExist(properties)) { + Object schedulerHints = properties.get("scheduler_hints"); + if (schedulerHints instanceof Map) { + addServerGroupHintsToPoliciesProups(translateTo, context, heatFileName, serviceTemplate, + heatOrchestrationTemplate, (Map<String, Object>) schedulerHints); + } else { + logger.warn("'scheduler_hints' property of resource '" + translateTo.getResourceId() + + "' is not valid. This property should be a map"); + } + } + } + + private void addServerGroupHintsToPoliciesProups(TranslateTo translateTo, + TranslationContext context, String heatFileName, + ServiceTemplate serviceTemplate, + HeatOrchestrationTemplate heatOrchestrationTemplate, + Map<String, Object> schedulerHints) { + for (Object hint : schedulerHints.values()) { + Optional<AttachedResourceId> attachedResourceId = HeatToToscaUtil + .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context, hint); + if (attachedResourceId.isPresent()) { + AttachedResourceId serverGroupResourceId = attachedResourceId.get(); + Object serverGroupResourceToTranslate = serverGroupResourceId.getEntityId(); + if (serverGroupResourceId.isGetResource()) { + boolean isHintOfTypeNovaServerGroup = + isHintOfTypeNovaServerGroup(heatOrchestrationTemplate, + serverGroupResourceToTranslate); + if (isHintOfTypeNovaServerGroup) { + addNovaServerToPolicyGroup(translateTo, context, heatFileName, serviceTemplate, + heatOrchestrationTemplate, (String) serverGroupResourceToTranslate); + } + } else if (serverGroupResourceId.isGetParam()) { + TranslatedHeatResource translatedServerGroupResource = + context.getHeatSharedResourcesByParam().get(serverGroupResourceToTranslate); + if (Objects.nonNull(translatedServerGroupResource) + && !HeatToToscaUtil.isHeatFileNested(translateTo, translateTo.getHeatFileName())) { + serviceTemplate.getTopology_template().getGroups() + .get(translatedServerGroupResource.getTranslatedId()).getMembers() + .add(translateTo.getTranslatedId()); + } + } + } + } + } + + private boolean isHintOfTypeNovaServerGroup(HeatOrchestrationTemplate heatOrchestrationTemplate, + Object resourceToTranslate) { + return heatOrchestrationTemplate.getResources().get(resourceToTranslate).getType() + .equals(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE.getHeatResource()); + } + + private void addNovaServerToPolicyGroup(TranslateTo translateTo, TranslationContext context, + String heatFileName, ServiceTemplate serviceTemplate, + HeatOrchestrationTemplate heatOrchestrationTemplate, + String resourceToTranslate) { + Resource serverGroup = + HeatToToscaUtil.getResource(heatOrchestrationTemplate, resourceToTranslate, heatFileName); + Optional<String> serverGroupTranslatedId = ResourceTranslationFactory.getInstance(serverGroup) + .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, serverGroup, + resourceToTranslate, context); + if (serverGroupTranslatedId.isPresent()) { + serviceTemplate.getTopology_template().getGroups().get(serverGroupTranslatedId.get()) + .getMembers().add(translateTo.getTranslatedId()); + } + } + + private boolean isSchedulerHintsPropExist(Map<String, Object> properties) { + return !MapUtils.isEmpty(properties) && Objects.nonNull(properties.get("scheduler_hints")); + } + + private void manageNovaServerBlockDeviceMapping(String heatFileName, + ServiceTemplate serviceTemplate, + NodeTemplate novaNodeTemplate, + HeatOrchestrationTemplate heatOrchestrationTemplate, + Resource resource, String resourceId, + String novaServerTranslatedId, + TranslationContext context) { + + List<Map<String, Object>> blockDeviceMappingList = getBlockDeviceMappingList(resource); + if (CollectionUtils.isEmpty(blockDeviceMappingList)) { + return; + } + + Object volumeIdObject; + Object snapshotIdObject; + String volumeResourceId; + int index = 0; + for (Map<String, Object> blockDeviceMapping : blockDeviceMappingList) { + volumeIdObject = blockDeviceMapping.get("volume_id"); + snapshotIdObject = blockDeviceMapping.get("snapshot_id"); + + if (volumeIdObject == null && snapshotIdObject == null) { + logger.warn("Resource '" + resourceId + + "' has block_device_mapping property with empty/missing volume_id and snapshot_id " + + "properties. Entry number " + + (index + 1) + ", this entry will be ignored in TOSCA translation."); + index++; + continue; + } + if (volumeIdObject == null) { + String deviceName = (String) blockDeviceMapping.get("device_name"); + String relationshipId = novaServerTranslatedId + "_" + index; + + Optional<AttachedResourceId> attachedSnapshotId = HeatToToscaUtil + .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context, + snapshotIdObject); + volumeResourceId = novaServerTranslatedId + "_" + attachedSnapshotId.get().getEntityId(); + createVolumeAttachesToRelationship(serviceTemplate, deviceName, novaServerTranslatedId, + volumeResourceId, relationshipId); + createCinderVolumeNodeTemplate(serviceTemplate, volumeResourceId, heatFileName, + blockDeviceMapping, heatOrchestrationTemplate, context); + connectNovaServerToVolume(novaNodeTemplate, volumeResourceId, relationshipId); + } else { + Optional<AttachedResourceId> attachedVolumeId = HeatToToscaUtil + .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context, + volumeIdObject); + if (attachedVolumeId.get().isGetResource()) { + connectNovaServerToVolume(novaNodeTemplate, + (String) attachedVolumeId.get().getTranslatedId(), null); + } + } + index++; + } + } + + private void connectNovaServerToVolume(NodeTemplate novaNodeTemplate, String volumeResourceId, + String relationshipId) { + RequirementAssignment requirementAssignment = new RequirementAssignment(); + requirementAssignment.setCapability(ToscaCapabilityType.ATTACHMENT.getDisplayName()); + requirementAssignment.setNode(volumeResourceId); + if (relationshipId != null) { + requirementAssignment.setRelationship(relationshipId); + } else { + requirementAssignment + .setRelationship(ToscaRelationshipType.NATIVE_ATTACHES_TO.getDisplayName()); + } + DataModelUtil + .addRequirementAssignment(novaNodeTemplate, ToscaConstants.LOCAL_STORAGE_REQUIREMENT_ID, + requirementAssignment); + } + + private void createCinderVolumeNodeTemplate(ServiceTemplate serviceTemplate, + String volumeResourceId, String heatFileName, + Map<String, Object> blockDeviceMapping, + HeatOrchestrationTemplate heatOrchestrationTemplate, + TranslationContext context) { + NodeTemplate cinderVolumeNodeTemplate = new NodeTemplate(); + cinderVolumeNodeTemplate.setType(ToscaNodeType.CINDER_VOLUME.getDisplayName()); + cinderVolumeNodeTemplate.setProperties(TranslatorHeatToToscaPropertyConverter + .getToscaPropertiesSimpleConversion(blockDeviceMapping, null, heatFileName, + heatOrchestrationTemplate, + HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource(), + cinderVolumeNodeTemplate, context)); + DataModelUtil.addNodeTemplate(serviceTemplate, volumeResourceId, cinderVolumeNodeTemplate); + } + + private void createVolumeAttachesToRelationship(ServiceTemplate serviceTemplate, + String deviceName, String novaServerTranslatedId, + String volumeId, String relationshipId) { + RelationshipTemplate relationshipTemplate = new RelationshipTemplate(); + relationshipTemplate.setType(ToscaRelationshipType.CINDER_VOLUME_ATTACHES_TO.getDisplayName()); + Map<String, Object> properties = new HashMap<>(); + properties.put("instance_uuid", novaServerTranslatedId); + properties.put("volume_id", volumeId); + if (deviceName != null) { + properties.put("device", deviceName); + } + relationshipTemplate.setProperties(properties); + + DataModelUtil.addRelationshipTemplate(serviceTemplate, relationshipId, relationshipTemplate); + } + + private List<Map<String, Object>> getBlockDeviceMappingList(Resource resource) { + + if (Objects.isNull(resource.getProperties())) { + return Collections.emptyList(); + } + List<Map<String, Object>> blockDeviceMappingList = + (List<Map<String, Object>>) resource.getProperties().get("block_device_mapping"); + List<Map<String, Object>> blockDeviceMappingV2List = + (List<Map<String, Object>>) resource.getProperties().get("block_device_mapping_v2"); + + if (blockDeviceMappingList != null && blockDeviceMappingV2List != null) { + blockDeviceMappingList.addAll(blockDeviceMappingV2List); + } else if (CollectionUtils.isEmpty(blockDeviceMappingList) + && CollectionUtils.isEmpty(blockDeviceMappingV2List)) { + return null; + + } else { + blockDeviceMappingList = + blockDeviceMappingList != null ? blockDeviceMappingList : blockDeviceMappingV2List; + } + return blockDeviceMappingList; + } + + private void manageNovaServerNetwork(String heatFileName, ServiceTemplate serviceTemplate, + HeatOrchestrationTemplate heatOrchestrationTemplate, + Resource resource, String translatedId, + TranslationContext context, NodeTemplate novaNodeTemplate) { + + if (resource.getProperties() == null) { + return; + } + List<Map<String, Object>> heatNetworkList = + (List<Map<String, Object>>) resource.getProperties().get("networks"); + + if (CollectionUtils.isEmpty(heatNetworkList)) { + return; + } + + for (Map<String, Object> heatNetwork : heatNetworkList) { + getOrTranslatePortTemplate(heatFileName, heatOrchestrationTemplate, + heatNetwork.get(Constants.PORT_PROPERTY_NAME), serviceTemplate, translatedId, context, + novaNodeTemplate); + } + + } + + private void getOrTranslatePortTemplate(String heatFileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + Object port, ServiceTemplate serviceTemplate, + String novaServerResourceId, TranslationContext context, + NodeTemplate novaNodeTemplate) { + Optional<AttachedResourceId> attachedPortId = HeatToToscaUtil + .extractAttachedResourceId(heatFileName, heatOrchestrationTemplate, context, port); + + if (!attachedPortId.isPresent()) { + return; + } + + if (attachedPortId.get().isGetResource()) { + String resourceId = (String) attachedPortId.get().getEntityId(); + Resource portResource = + HeatToToscaUtil.getResource(heatOrchestrationTemplate, resourceId, heatFileName); + if (!Arrays.asList(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource(), + HeatResourcesTypes.CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE.getHeatResource()) + .contains(portResource.getType())) { + logger.warn("NovaServer connect to port resource with id : " + resourceId + " and type : " + + portResource.getType() + + ". This resource type is not supported, therefore the connection to the port is " + + "ignored. " + + "Supported types are: " + + HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource() + ", " + + HeatResourcesTypes.CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE + .getHeatResource()); + return; + } else if (HeatResourcesTypes.CONTRAIL_V2_VIRTUAL_MACHINE_INTERFACE_RESOURCE_TYPE + .getHeatResource().equals(portResource.getType())) { + Map<String, Object> properties = portResource.getProperties(); + if (!MapUtils.isEmpty(properties) && Objects.nonNull(properties.get("port_tuple_refs"))) { + novaNodeTemplate.getProperties().put("contrail_service_instance_ind", true); + } + } + Optional<String> translatedPortId = ResourceTranslationFactory.getInstance(portResource) + .translateResource(heatFileName, serviceTemplate, heatOrchestrationTemplate, portResource, + resourceId, context); + if (translatedPortId.isPresent()) { + NodeTemplate portNodeTemplate = + DataModelUtil.getNodeTemplate(serviceTemplate, translatedPortId.get()); + addBindingReqFromPortToCompute(novaServerResourceId, portNodeTemplate); + } else { + logger.warn("NovaServer connect to port resource with id : " + resourceId + " and type : " + + portResource.getType() + + ". This resource type is not supported, therefore the connection to the port is " + + "ignored."); + } + } + } + + /** + * Create local node type string. + * + * @param serviceTemplate the service template + * @param properties the properties + * @param resourceTranslatedId the resource translated id + * @return the string + */ + public String createLocalNodeType(ServiceTemplate serviceTemplate, Map<String, Object> properties, + String resourceTranslatedId) { + NameExtractorService nodeTypeNameExtractor = new NameExtractorServiceImpl(); + List<PropertyRegexMatcher> propertyRegexMatchers = + getPropertiesAndRegexMatchers(nodeTypeNameExtractor); + Optional<String> extractedNodeTypeName = nodeTypeNameExtractor + .extractNodeTypeNameByPropertiesPriority(properties, propertyRegexMatchers); + + String nodeTypeName = ToscaConstants.NODES_PREFIX + + (extractedNodeTypeName.isPresent() ? extractedNodeTypeName.get() + : resourceTranslatedId.replace(".", "_")); + if (!isNodeTypeCreated(serviceTemplate, nodeTypeName)) { + DataModelUtil.addNodeType(serviceTemplate, nodeTypeName, createNodeType()); + } + return nodeTypeName; + } + + private List<PropertyRegexMatcher> getPropertiesAndRegexMatchers( + NameExtractorService nodeTypeNameExtractor) { + List<PropertyRegexMatcher> propertyRegexMatchers = new ArrayList<>(); + propertyRegexMatchers.add(nodeTypeNameExtractor + .getPropertyRegexMatcher(Constants.NAME_PROPERTY_NAME, + Arrays.asList(".+_name$", ".+_names$", ".+_name_[0-9]+"), "_name")); + propertyRegexMatchers.add(nodeTypeNameExtractor + .getPropertyRegexMatcher("image", Collections.singletonList(".+_image_name$"), + "_image_name")); + propertyRegexMatchers.add(nodeTypeNameExtractor + .getPropertyRegexMatcher("flavor", Collections.singletonList(".+_flavor_name$"), + "_flavor_name")); + return propertyRegexMatchers; + } + + private boolean isNodeTypeCreated(ServiceTemplate serviceTemplate, String nodeTypeName) { + return !MapUtils.isEmpty(serviceTemplate.getNode_types()) + && Objects.nonNull(serviceTemplate.getNode_types().get(nodeTypeName)); + } + + private NodeType createNodeType() { + NodeType nodeType = new NodeType(); + nodeType.setDerived_from(ToscaNodeType.NOVA_SERVER.getDisplayName()); + return nodeType; + } +} |