package alien4cloud.orchestrators.locations.services; import java.util.List; import java.util.Set; import javax.inject.Inject; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import alien4cloud.exception.NotFoundException; import org.alien4cloud.tosca.model.CSARDependency; import org.alien4cloud.tosca.model.types.NodeType; import alien4cloud.model.orchestrators.locations.LocationResourceTemplate; import org.alien4cloud.tosca.model.templates.Capability; import org.alien4cloud.tosca.model.templates.NodeTemplate; import alien4cloud.orchestrators.plugin.ILocationResourceAccessor; import alien4cloud.topology.TopologyServiceCore; import com.google.common.base.Objects; import com.google.common.collect.Lists; /** * Location Resource Generator Service provides utilities to generate location resources . */ @Component @Slf4j public class LocationResourceGeneratorService { @Inject private TopologyServiceCore topologyService; @Getter @Setter @NoArgsConstructor @AllArgsConstructor(suppressConstructorProperties = true) public static class ImageFlavorContext { private List<LocationResourceTemplate> templates; private String idPropertyName; } @Getter @Setter @NoArgsConstructor @AllArgsConstructor(suppressConstructorProperties = true) public static class ComputeContext { private List<NodeType> nodeTypes = Lists.newArrayList(); private String generatedNamePrefix; private String imageIdPropertyName; private String flavorIdPropertyName; } /** * Generate resources of type compute given a set of images and flavors * * @param imageContext * @param flavorContext * @param computeContext * @param resourceAccessor * @return */ public List<LocationResourceTemplate> generateComputeFromImageAndFlavor(ImageFlavorContext imageContext, ImageFlavorContext flavorContext, ComputeContext computeContext, ILocationResourceAccessor resourceAccessor) { List<LocationResourceTemplate> images = imageContext.getTemplates(); List<LocationResourceTemplate> flavors = flavorContext.getTemplates(); Set<CSARDependency> dependencies = resourceAccessor.getDependencies(); List<LocationResourceTemplate> generated = Lists.newArrayList(); for (LocationResourceTemplate image : images) { for (LocationResourceTemplate flavor : flavors) { String defaultComputeName = generateDefaultName(image, flavor); int count = 0; for (NodeType indexedNodeType : computeContext.getNodeTypes()) { String name = StringUtils.isNotBlank(computeContext.getGeneratedNamePrefix()) ? computeContext.getGeneratedNamePrefix() : defaultComputeName; if (count > 0) { name = name + "_" + count; } NodeTemplate node = topologyService.buildNodeTemplate(dependencies, indexedNodeType, null); // set the imageId node.getProperties() .put(computeContext.getImageIdPropertyName(), image.getTemplate().getProperties().get(imageContext.getIdPropertyName())); // set the flavorId node.getProperties().put(computeContext.getFlavorIdPropertyName(), flavor.getTemplate().getProperties().get(flavorContext.getIdPropertyName())); // copy os and host capabilities properties copyCapabilityBasedOnTheType(image.getTemplate(), node, "os"); copyCapabilityBasedOnTheType(flavor.getTemplate(), node, "host"); LocationResourceTemplate resource = new LocationResourceTemplate(); resource.setService(false); resource.setTemplate(node); resource.setName(name); count++; generated.add(resource); } } } return generated; } private String generateDefaultName(LocationResourceTemplate image, LocationResourceTemplate flavor) { return flavor.getName() + "_" + image.getName(); } /** * Copy a capability based on its type from a node to another * * @param from * @param to * @param capabilityName */ private void copyCapabilityBasedOnTheType(NodeTemplate from, NodeTemplate to, String capabilityName) { if (MapUtils.isEmpty(from.getCapabilities()) || MapUtils.isEmpty(to.getCapabilities())) { return; } Capability capa = to.getCapabilities().get(capabilityName); if (capa != null) { // copy the first found and exit for (Capability capaToCheck : from.getCapabilities().values()) { if (Objects.equal(capaToCheck.getType(), capa.getType())) { to.getCapabilities().put(capabilityName, capaToCheck); return; } } } } public ImageFlavorContext buildContext(String elementType, String idPropertyName, ILocationResourceAccessor resourceAccessor) { return new ImageFlavorContext(resourceAccessor.getResources(elementType), idPropertyName); } public ComputeContext buildComputeContext(String elementType, String namePefix, String imageIdPropertyName, String flavorIdPropertyName, ILocationResourceAccessor resourceAccessor) { ComputeContext context = new ComputeContext(); context.setFlavorIdPropertyName(flavorIdPropertyName); context.setImageIdPropertyName(imageIdPropertyName); context.setGeneratedNamePrefix(namePefix); try { NodeType nodeType = resourceAccessor.getIndexedToscaElement(elementType); context.getNodeTypes().add(nodeType); } catch (NotFoundException e) { log.warn("No compute found with the element id: " + elementType, e); } return context; } }