org.openecomp.sdc.translator.services.heattotosca.impl.ResourceTranslationNovaServerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.openecomp.sdc.translator.services.heattotosca.impl.ResourceTranslationNovaServerImpl.java

Source

/*-
 * ============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;
    }
}