package alien4cloud.orchestrators.locations.services; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.annotation.Resource; import javax.inject.Inject; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import alien4cloud.component.ICSARRepositorySearchService; import alien4cloud.dao.IGenericSearchDAO; import alien4cloud.dao.model.GetMultipleDataResult; import alien4cloud.events.LocationTemplateCreated; import alien4cloud.exception.NotFoundException; import org.alien4cloud.tosca.model.CSARDependency; import org.alien4cloud.tosca.model.definitions.CapabilityDefinition; import org.alien4cloud.tosca.model.types.CapabilityType; import alien4cloud.model.components.IndexedModelUtils; import org.alien4cloud.tosca.model.types.NodeType; import org.alien4cloud.tosca.model.types.AbstractToscaType; import org.alien4cloud.tosca.model.definitions.PropertyDefinition; import alien4cloud.model.orchestrators.Orchestrator; import alien4cloud.model.orchestrators.locations.Location; import alien4cloud.model.orchestrators.locations.LocationResourceTemplate; import alien4cloud.model.orchestrators.locations.LocationResources; import org.alien4cloud.tosca.model.templates.Capability; import org.alien4cloud.tosca.model.templates.NodeTemplate; import alien4cloud.orchestrators.plugin.ILocationConfiguratorPlugin; import alien4cloud.orchestrators.plugin.ILocationResourceAccessor; import alien4cloud.orchestrators.plugin.IOrchestratorPlugin; import alien4cloud.orchestrators.services.OrchestratorService; import alien4cloud.paas.OrchestratorPluginService; import alien4cloud.topology.TopologyServiceCore; import alien4cloud.topology.TopologyUtils; import alien4cloud.tosca.properties.constraints.exception.ConstraintValueDoNotMatchPropertyTypeException; import alien4cloud.tosca.properties.constraints.exception.ConstraintViolationException; import alien4cloud.utils.MapUtil; import alien4cloud.utils.ReflectionUtil; import alien4cloud.utils.services.PropertyService; /** * Location Resource Service provides utilities to query LocationResourceTemplate. */ @Component("location-resource-service") public class LocationResourceService implements ILocationResourceService { @Resource(name = "alien-es-dao") private IGenericSearchDAO alienDAO; @Inject private ICSARRepositorySearchService csarRepoSearchService; @Inject private TopologyServiceCore topologyService; @Inject private LocationService locationService; @Inject private OrchestratorService orchestratorService; @Inject private OrchestratorPluginService orchestratorPluginService; @Resource private PropertyService propertyService; @Inject private ApplicationContext applicationContext; /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#getLocationResources(alien4cloud.model.orchestrators.locations.Location) */ @Override public LocationResources getLocationResources(Location location) { Orchestrator orchestrator = orchestratorService.get(location.getOrchestratorId()); if (orchestrator != null && orchestratorPluginService.get(orchestrator.getId()) != null) { return getLocationResourcesFromOrchestrator(location); } List<LocationResourceTemplate> locationResourceTemplates = getResourcesTemplates(location.getId()); LocationResources locationResources = new LocationResources(getLocationResourceTypes(locationResourceTemplates)); setLocationRessource(locationResourceTemplates, locationResources); return locationResources; } /* * (non-Javadoc) * * @see * alien4cloud.orchestrators.locations.services.ILocationResourceService#getLocationResourcesFromOrchestrator(alien4cloud.model.orchestrators.locations. * Location) */ @Override public LocationResources getLocationResourcesFromOrchestrator(Location location) { LocationResources locationResources = new LocationResources(); Orchestrator orchestrator = orchestratorService.getOrFail(location.getOrchestratorId()); IOrchestratorPlugin orchestratorInstance = (IOrchestratorPlugin) orchestratorPluginService.getOrFail(orchestrator.getId()); ILocationConfiguratorPlugin configuratorPlugin = orchestratorInstance.getConfigurator(location.getInfrastructureType()); List<String> allExposedTypes = configuratorPlugin.getResourcesTypes(); setLocationRessourceTypes(allExposedTypes, location, locationResources); List<LocationResourceTemplate> locationResourceTemplates = getResourcesTemplates(location.getId()); setLocationRessource(locationResourceTemplates, locationResources); return locationResources; } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#getLocationResourceTypes(java.util.Collection) */ @Override public LocationResourceTypes getLocationResourceTypes(Collection<LocationResourceTemplate> resourceTemplates) { Map<String, Set<String>> resourceTypesByLocationId = Maps.newHashMap(); for (LocationResourceTemplate resourceTemplate : resourceTemplates) { Set<String> locationResourceTypes = resourceTypesByLocationId.get(resourceTemplate.getLocationId()); if (locationResourceTypes == null) { locationResourceTypes = Sets.newHashSet(); resourceTypesByLocationId.put(resourceTemplate.getLocationId(), locationResourceTypes); } locationResourceTypes.add(resourceTemplate.getTemplate().getType()); } LocationResourceTypes locationResourceTypes = new LocationResourceTypes(); for (Map.Entry<String, Set<String>> resourceTypeByLocationIdEntry : resourceTypesByLocationId.entrySet()) { String locationId = resourceTypeByLocationIdEntry.getKey(); Set<String> exposedTypes = resourceTypeByLocationIdEntry.getValue(); Location location = locationService.getOrFail(locationId); setLocationRessourceTypes(exposedTypes, location, locationResourceTypes); } return locationResourceTypes; } /** * Put the exposed types to the appropriate List of locationResourceTypes passed as param */ private void setLocationRessourceTypes(Collection<String> exposedTypes, Location location, LocationResourceTypes locationResourceTypes) { for (String exposedType : exposedTypes) { NodeType exposedIndexedNodeType = csarRepoSearchService.getRequiredElementInDependencies(NodeType.class, exposedType, location.getDependencies()); if (exposedIndexedNodeType.isAbstract()) { locationResourceTypes.getConfigurationTypes().put(exposedType, exposedIndexedNodeType); } else { locationResourceTypes.getNodeTypes().put(exposedType, exposedIndexedNodeType); } if (exposedIndexedNodeType.getCapabilities() != null && !exposedIndexedNodeType.getCapabilities().isEmpty()) { for (CapabilityDefinition capabilityDefinition : exposedIndexedNodeType.getCapabilities()) { locationResourceTypes.getCapabilityTypes().put(capabilityDefinition.getType(), csarRepoSearchService .getRequiredElementInDependencies(CapabilityType.class, capabilityDefinition.getType(), location.getDependencies())); } } } } /** * Put the locationResourceTemplates to the appropriate List of the locationResources passed as param */ private void setLocationRessource(List<LocationResourceTemplate> locationResourceTemplates, LocationResources locationResources) { for (LocationResourceTemplate resourceTemplate : locationResourceTemplates) { String templateType = resourceTemplate.getTemplate().getType(); if (locationResources.getConfigurationTypes().containsKey(templateType)) { locationResources.getConfigurationTemplates().add(resourceTemplate); } if (locationResources.getNodeTypes().containsKey(templateType)) { locationResources.getNodeTemplates().add(resourceTemplate); } } } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#accessor(java.lang.String) */ @Override public ILocationResourceAccessor accessor(final String locationId) { return new ILocationResourceAccessor() { private Location location = locationService.getOrFail(locationId); @Override public List<LocationResourceTemplate> getResources() { return getResourcesTemplates(locationId); } @Override public List<LocationResourceTemplate> getResources(String type) { // Get all types that derives from the current type. String[] types = new String[] { type }; // Get all the location resources templates for the given type. Map<String, String[]> filter = getLocationIdFilter(locationId); filter.put("types", types); return getResourcesTemplates(filter); } @Override public <T extends AbstractToscaType> T getIndexedToscaElement(String type) { return (T) csarRepoSearchService.getRequiredElementInDependencies(AbstractToscaType.class, type, location.getDependencies()); } @Override public Set<CSARDependency> getDependencies() { return location.getDependencies(); } }; } private Map<String, String[]> getLocationIdFilter(String locationId) { return MapUtil.newHashMap(new String[] { "locationId" }, new String[][] { new String[] { locationId } }); } private List<LocationResourceTemplate> getResourcesTemplates(Map<String, String[]> filter) { // get all defined resources for this resource. GetMultipleDataResult<LocationResourceTemplate> result = alienDAO.find(LocationResourceTemplate.class, filter, Integer.MAX_VALUE); if (result.getData() == null) { return Lists.newArrayList(); } return Lists.newArrayList(result.getData()); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#getResourcesTemplates(java.lang.String) */ @Override public List<LocationResourceTemplate> getResourcesTemplates(String locationId) { return getResourcesTemplates(getLocationIdFilter(locationId)); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#getMultiple(java.util.Collection) */ @Override public Map<String, LocationResourceTemplate> getMultiple(Collection<String> ids) { Map<String, LocationResourceTemplate> result = Maps.newHashMap(); if (CollectionUtils.isNotEmpty(ids)) { List<LocationResourceTemplate> templates = alienDAO.findByIds(LocationResourceTemplate.class, ids.toArray(new String[ids.size()])); for (LocationResourceTemplate template : templates) { result.put(template.getId(), template); } } return result; } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#addResourceTemplate(java.lang.String, java.lang.String, java.lang.String) */ @Override public LocationResourceTemplate addResourceTemplate(String locationId, String resourceName, String resourceTypeName) { Location location = locationService.getOrFail(locationId); NodeType resourceType = csarRepoSearchService.getRequiredElementInDependencies(NodeType.class, resourceTypeName, location.getDependencies()); NodeTemplate nodeTemplate = topologyService.buildNodeTemplate(location.getDependencies(), resourceType, null); // FIXME Workaround to remove default scalable properties from compute TopologyUtils.setNullScalingPolicy(nodeTemplate, resourceType); LocationResourceTemplate locationResourceTemplate = new LocationResourceTemplate(); locationResourceTemplate.setName(resourceName); locationResourceTemplate.setEnabled(true); locationResourceTemplate.setGenerated(false); locationResourceTemplate.setId(UUID.randomUUID().toString()); locationResourceTemplate.setLocationId(locationId); locationResourceTemplate.setService(false); locationResourceTemplate.setTypes(Lists.<String> newArrayList(resourceType.getElementId())); locationResourceTemplate.getTypes().addAll(resourceType.getDerivedFrom()); locationResourceTemplate.setTemplate(nodeTemplate); LocationTemplateCreated event = new LocationTemplateCreated(this); event.setTemplate(locationResourceTemplate); event.setLocation(location); event.setNodeType(resourceType); applicationContext.publishEvent(event); saveResource(location, locationResourceTemplate); return locationResourceTemplate; } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#deleteResourceTemplate(java.lang.String) */ @Override public void deleteResourceTemplate(String resourceId) { LocationResourceTemplate resourceTemplate = getOrFail(resourceId); Location location = locationService.getOrFail(resourceTemplate.getLocationId()); alienDAO.delete(LocationResourceTemplate.class, resourceId); alienDAO.save(location); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#getOrFail(java.lang.String) */ @Override public LocationResourceTemplate getOrFail(String resourceId) { LocationResourceTemplate locationResourceTemplate = alienDAO.findById(LocationResourceTemplate.class, resourceId); if (locationResourceTemplate == null) { throw new NotFoundException("Location Resource Template [" + resourceId + "] doesn't exists."); } return locationResourceTemplate; } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#merge(java.lang.Object, java.lang.String) */ @Override public void merge(Object mergeRequest, String resourceId) { LocationResourceTemplate resourceTemplate = getOrFail(resourceId); ReflectionUtil.mergeObject(mergeRequest, resourceTemplate); saveResource(resourceTemplate); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#setTemplateProperty(java.lang.String, java.lang.String, java.lang.Object) */ @Override public void setTemplateProperty(String resourceId, String propertyName, Object propertyValue) throws ConstraintValueDoNotMatchPropertyTypeException, ConstraintViolationException { LocationResourceTemplate resourceTemplate = getOrFail(resourceId); Location location = locationService.getOrFail(resourceTemplate.getLocationId()); NodeType resourceType = csarRepoSearchService.getRequiredElementInDependencies(NodeType.class, resourceTemplate.getTemplate().getType(), location.getDependencies()); if (resourceType.getProperties() == null || !resourceType.getProperties().containsKey(propertyName)) { throw new NotFoundException("Property <" + propertyName + "> is not found in type <" + resourceType.getElementId() + ">"); } propertyService.setPropertyValue(location.getDependencies(), resourceTemplate.getTemplate(), resourceType.getProperties().get(propertyName), propertyName, propertyValue); saveResource(resourceTemplate); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#setTemplateCapabilityProperty(alien4cloud.model.orchestrators.locations. * LocationResourceTemplate, java.lang.String, java.lang.String, java.lang.Object) */ @Override public void setTemplateCapabilityProperty(LocationResourceTemplate resourceTemplate, String capabilityName, String propertyName, Object propertyValue) throws ConstraintViolationException, ConstraintValueDoNotMatchPropertyTypeException { Location location = locationService.getOrFail(resourceTemplate.getLocationId()); NodeType resourceType = csarRepoSearchService.getRequiredElementInDependencies(NodeType.class, resourceTemplate.getTemplate().getType(), location.getDependencies()); Capability capability = getOrFailCapability(resourceTemplate.getTemplate(), capabilityName); CapabilityDefinition capabilityDefinition = getOrFailCapabilityDefinition(resourceType, capabilityName); CapabilityType capabilityType = csarRepoSearchService.getRequiredElementInDependencies(CapabilityType.class, capabilityDefinition.getType(), location.getDependencies()); PropertyDefinition propertyDefinition = getOrFailCapabilityPropertyDefinition(capabilityType, propertyName); propertyService.setCapabilityPropertyValue(capability, propertyDefinition, propertyName, propertyValue); } private Capability getOrFailCapability(NodeTemplate nodeTemplate, String capabilityName) { Capability capability = MapUtils.getObject(nodeTemplate.getCapabilities(), capabilityName); if (capability != null) { return capability; } throw new NotFoundException("Capability <" + capabilityName + "> not found in template."); } private PropertyDefinition getOrFailCapabilityPropertyDefinition(CapabilityType capabilityType, String propertyName) { PropertyDefinition propertyDefinition = MapUtils.getObject(capabilityType.getProperties(), propertyName); if (propertyDefinition != null) { return propertyDefinition; } throw new NotFoundException("Property <" + propertyName + "> not found in capability type <" + capabilityType.getElementId() + ">"); } private CapabilityDefinition getOrFailCapabilityDefinition(NodeType resourceType, String capabilityName) { CapabilityDefinition capabilityDefinition = IndexedModelUtils.getCapabilityDefinitionById(resourceType.getCapabilities(), capabilityName); if (capabilityDefinition != null) { return capabilityDefinition; } throw new NotFoundException("Capability <" + capabilityName + "> not found in type <" + resourceType.getElementId() + ">"); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#setTemplateCapabilityProperty(java.lang.String, java.lang.String, * java.lang.String, java.lang.Object) */ @Override public void setTemplateCapabilityProperty(String resourceId, String capabilityName, String propertyName, Object propertyValue) throws ConstraintViolationException, ConstraintValueDoNotMatchPropertyTypeException { LocationResourceTemplate resourceTemplate = getOrFail(resourceId); setTemplateCapabilityProperty(resourceTemplate, capabilityName, propertyName, propertyValue); saveResource(resourceTemplate); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#autoConfigureResources(java.lang.String) */ @Override public List<LocationResourceTemplate> autoConfigureResources(String locationId) { return locationService.autoConfigure(locationId); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#deleteGeneratedResources(java.lang.String) */ @Override public void deleteGeneratedResources(String locationId) { QueryBuilder locationIdQuery = QueryBuilders.termQuery("locationId", locationId); QueryBuilder generatedFieldQuery = QueryBuilders.termQuery("generated", true); // QueryBuilder builder = QueryBuilders.filteredQuery(locationIdQuery, filterBuilder); QueryBuilder builder = QueryBuilders.boolQuery().must(locationIdQuery).must(generatedFieldQuery); Location location = locationService.getOrFail(locationId); alienDAO.delete(LocationResourceTemplate.class, builder); alienDAO.save(location); } /* * (non-Javadoc) * * @see alien4cloud.orchestrators.locations.services.ILocationResourceService#saveResource(alien4cloud.model.orchestrators.locations.Location, * alien4cloud.model.orchestrators.locations.LocationResourceTemplate) */ @Override public void saveResource(Location location, LocationResourceTemplate resourceTemplate) { alienDAO.save(location); alienDAO.save(resourceTemplate); } /* * (non-Javadoc) * * @see * alien4cloud.orchestrators.locations.services.ILocationResourceService#saveResource(alien4cloud.model.orchestrators.locations.LocationResourceTemplate) */ @Override public void saveResource(LocationResourceTemplate resourceTemplate) { Location location = locationService.getOrFail(resourceTemplate.getLocationId()); saveResource(location, resourceTemplate); } }