/******************************************************************************* * Copyright (c) 2013 GigaSpaces Technologies Ltd. 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. *******************************************************************************/ package org.cloudifysource.rest.deploy; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.logging.Logger; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.cloudifysource.domain.ComputeDetails; import org.cloudifysource.domain.DataGrid; import org.cloudifysource.domain.Service; import org.cloudifysource.domain.Sla; import org.cloudifysource.domain.StatefulProcessingUnit; import org.cloudifysource.domain.StatelessProcessingUnit; import org.cloudifysource.domain.cloud.Cloud; import org.cloudifysource.domain.cloud.compute.ComputeTemplate; import org.cloudifysource.dsl.internal.CloudifyConstants; import org.cloudifysource.dsl.internal.packaging.ZipUtils; import org.cloudifysource.dsl.rest.request.InstallServiceRequest; import org.cloudifysource.dsl.utils.ServiceUtils; import org.cloudifysource.esc.driver.provisioning.CloudifyMachineProvisioningConfig; import org.cloudifysource.rest.RestConfiguration; import org.cloudifysource.rest.controllers.ElasticScaleConfigFactory; import org.cloudifysource.rest.util.IsolationUtils; import org.codehaus.jackson.map.ObjectMapper; import org.openspaces.admin.pu.elastic.ElasticStatefulProcessingUnitDeployment; import org.openspaces.admin.pu.elastic.ElasticStatelessProcessingUnitDeployment; import org.openspaces.admin.pu.elastic.config.AutomaticCapacityScaleConfig; import org.openspaces.admin.pu.elastic.config.DiscoveredMachineProvisioningConfig; import org.openspaces.admin.pu.elastic.config.DiscoveredMachineProvisioningConfigurer; import org.openspaces.admin.pu.elastic.config.ManualCapacityScaleConfig; import org.openspaces.admin.pu.elastic.config.ManualCapacityScaleConfigurer; import org.openspaces.admin.pu.elastic.topology.ElasticDeploymentTopology; import org.openspaces.admin.space.ElasticSpaceDeployment; import org.openspaces.core.util.MemoryUnit; /** * Elastic deployment factory class. * * @author adaml * @since 2.6.0 */ public class ElasticProcessingUnitDeploymentFactoryImpl implements ElasticProcessingUnitDeploymentFactory { private static final Logger logger = Logger .getLogger(ElasticProcessingUnitDeploymentFactoryImpl.class.getName()); private static final String LOCALCLOUD_ZONE = "localcloud"; private DeploymentConfig deploymentConfig; // this should be used to create temp directories in the shared temp location. private final RestConfiguration restConfig; public ElasticProcessingUnitDeploymentFactoryImpl(final RestConfiguration restConfig) { this.restConfig = restConfig; } @Override public ElasticDeploymentTopology create(final DeploymentConfig deploymentConfig) throws ElasticDeploymentCreationException { final Service service = deploymentConfig.getService(); this.deploymentConfig = deploymentConfig; if (service.getLifecycle() != null) { return createElasticUSMDeployment(); } else if (service.getStatefulProcessingUnit() != null) { return createElasticStatefulProcessingUnit(); } else if (service.getStatelessProcessingUnit() != null || service.getMirrorProcessingUnit() != null) { return createElasticStatelessPUDeployment(); } else if (service.getDataGrid() != null) { return createElasticDatagridDeployment(); } else { throw new ElasticDeploymentCreationException("Unsupported service type"); } } private ElasticSpaceDeployment createElasticDatagridDeployment() { final String absolutePUName = deploymentConfig.getAbsolutePUName(); final ElasticSpaceDeployment deployment = new ElasticSpaceDeployment(absolutePUName); addSharedDeploymentParameters(deployment); final DataGrid dataGrid = deploymentConfig.getService().getDataGrid(); addProcessingUnitContextProperties(deployment, dataGrid.getContextProperties()); final Sla puSla = dataGrid.getSla(); prepareSla(puSla); final int containerMemoryInMB = puSla.getMemoryCapacityPerContainer(); final int maxMemoryInMB = puSla.getMaxMemoryCapacity(); deployment .memoryCapacityPerContainer(containerMemoryInMB, MemoryUnit.MEGABYTES) .maxMemoryCapacity(maxMemoryInMB, MemoryUnit.MEGABYTES) .highlyAvailable(puSla.getHighlyAvailable()) // allow single machine for local development purposes .singleMachineDeployment(); ManualCapacityScaleConfig scaleConfig; if (isLocalcloud()) { final Integer memoryCapacity = puSla.getMemoryCapacity(); scaleConfig = new ManualCapacityScaleConfigurer() .memoryCapacity(memoryCapacity, MemoryUnit.MEGABYTES).create(); } else { final long cloudExternalProcessMemoryInMB = calculateExternalProcessMemory(); deployment.memoryCapacityPerContainer((int) cloudExternalProcessMemoryInMB, MemoryUnit.MEGABYTES); scaleConfig = ElasticScaleConfigFactory .createManualCapacityScaleConfig((int) cloudExternalProcessMemoryInMB, 0, deploymentConfig.getService().isLocationAware(), true); // TODO: [itaif] Why only capacity of one container ? } deployment.scale(scaleConfig); return deployment; } private void addProcessingUnitContextProperties(final ElasticDeploymentTopology deployment, final Map<String, String> properties) { if (properties != null) { for (final Entry<String, String> entry : properties.entrySet()) { deployment.addContextProperty(entry.getKey(), entry.getValue()); } } } // TODO - temp files should be created in shared temp location, as read from restConfig private File getBinaryFromPackedRecipe(final File packedService, final String binaryName) throws IOException { final File tempFile = File.createTempFile(binaryName, ""); tempFile.delete(); ZipUtils.unzip(packedService, tempFile); final File destFile = new File(tempFile, "ext/" + binaryName); if (!destFile.exists()) { throw new FileNotFoundException("deployment file/folder " + binaryName + " could not be found"); } if (destFile.isDirectory()) { final File jarFile = File.createTempFile( destFile.getName(), ".jar"); jarFile.delete(); ZipUtils.zip(destFile, jarFile); return jarFile; } return destFile; } private ElasticStatelessProcessingUnitDeployment createElasticStatelessPUDeployment() throws ElasticDeploymentCreationException { final Service service = deploymentConfig.getService(); final StatelessProcessingUnit puConfig; if (service.getStatelessProcessingUnit() != null) { puConfig = service.getStatelessProcessingUnit(); } else { puConfig = service.getMirrorProcessingUnit(); } final Sla statelessSla = puConfig.getSla(); final int containerMemoryInMB = statelessSla.getMemoryCapacityPerContainer(); prepareSla(statelessSla); // TODO: why is there no maxMemory? final File packedService = deploymentConfig.getPackedFile(); final String binaryFileName = deploymentConfig.getService().getStatelessProcessingUnit().getBinaries(); File binaryFile = null; try { binaryFile = getBinaryFromPackedRecipe(packedService, binaryFileName); } catch (final IOException e) { throw new ElasticDeploymentCreationException("Failed to open packaged service file: " + e.getMessage(), e); } final ElasticStatelessProcessingUnitDeployment deployment = new ElasticStatelessProcessingUnitDeployment( binaryFile) .memoryCapacityPerContainer(containerMemoryInMB, MemoryUnit.MEGABYTES); // Shared properties among all deployment types addSharedDeploymentParameters(deployment); addProcessingUnitContextProperties(deployment, puConfig.getContextProperties()); setSpringProfilesActive(deployment, puConfig.getSpringProfilesActive()); ManualCapacityScaleConfig scaleConfig; if (isLocalcloud()) { scaleConfig = new ManualCapacityScaleConfigurer() .memoryCapacity(containerMemoryInMB * service.getNumInstances(), MemoryUnit.MEGABYTES).create(); } else { final long cloudExternalProcessMemoryInMB = calculateExternalProcessMemory(); deployment.memoryCapacityPerContainer( (int) cloudExternalProcessMemoryInMB, MemoryUnit.MEGABYTES); // create manual standard scale config scaleConfig = ElasticScaleConfigFactory .createManualCapacityScaleConfig(containerMemoryInMB * service.getNumInstances(), 0, service.isLocationAware(), true); } deployment.scale(scaleConfig); return deployment; } private void setSpringProfilesActive( final ElasticDeploymentTopology deployment, final String profiles) { if (StringUtils.isNotBlank(profiles)) { deployment.commandLineArgument("-Dspring.profiles.active=" + profiles); } } private ElasticStatefulProcessingUnitDeployment createElasticStatefulProcessingUnit() throws ElasticDeploymentCreationException { final StatefulProcessingUnit puConfig = deploymentConfig.getService().getStatefulProcessingUnit(); final Sla statefulSla = puConfig.getSla(); prepareSla(statefulSla); final File packedService = deploymentConfig.getPackedFile(); final String binaryFileName = deploymentConfig.getService().getStatefulProcessingUnit().getBinaries(); File binaryFile = null; try { binaryFile = getBinaryFromPackedRecipe(packedService, binaryFileName); } catch (final IOException e) { throw new ElasticDeploymentCreationException("Failed to open packaged service file: " + e.getMessage(), e); } final ElasticStatefulProcessingUnitDeployment deployment = new ElasticStatefulProcessingUnitDeployment(binaryFile); // Shared properties among all deployment types addSharedDeploymentParameters(deployment); addProcessingUnitContextProperties(deployment, puConfig.getContextProperties()); // TODO:The sla should also be available in a usm service. // these properties should be set if defined to overrride the properties set in the cloud groovy. final int containerMemoryInMB = statefulSla.getMemoryCapacityPerContainer(); final int maxMemoryCapacityInMB = statefulSla.getMaxMemoryCapacity(); deployment.memoryCapacityPerContainer(containerMemoryInMB, MemoryUnit.MEGABYTES) .maxMemoryCapacity(maxMemoryCapacityInMB, MemoryUnit.MEGABYTES) .highlyAvailable(statefulSla.getHighlyAvailable()) .singleMachineDeployment(); setSpringProfilesActive(deployment, puConfig.getSpringProfilesActive()); ManualCapacityScaleConfig scaleConfig; final int memoryCapacity = statefulSla.getMemoryCapacity(); if (isLocalcloud()) { // setting localcloud scale config scaleConfig = new ManualCapacityScaleConfigurer() .memoryCapacity(memoryCapacity, MemoryUnit.MEGABYTES).create(); } else { // create manual standard scale config scaleConfig = ElasticScaleConfigFactory .createManualCapacityScaleConfig(memoryCapacity, 0, deploymentConfig.getService().isLocationAware(), true); } deployment.scale(scaleConfig); return deployment; } private ElasticStatelessProcessingUnitDeployment createElasticUSMDeployment() throws ElasticDeploymentCreationException { File packedFile = deploymentConfig.getPackedFile(); if (packedFile.exists()) { packedFile = createExpectedFile(packedFile); } final ElasticStatelessProcessingUnitDeployment deployment = new ElasticStatelessProcessingUnitDeployment(packedFile); // Shared properties among all deployment types addSharedDeploymentParameters(deployment); deployment.addContextProperty(CloudifyConstants.CONTEXT_PROPERTY_ASYNC_INSTALL, "true"); final String disableSelHealingValue = Boolean.toString(!deploymentConfig.getInstallRequest().getSelfHealing()); logger.info("Setting disable self healing value to: " + disableSelHealingValue); deployment.addContextProperty(CloudifyConstants.CONTEXT_PROPERTY_DISABLE_SELF_HEALING, disableSelHealingValue); deployment.name(this.deploymentConfig.getAbsolutePUName()); final Service service = deploymentConfig.getService(); final boolean scalingRulesDefined = service.getScalingRules() == null ? false : true; if (!isLocalcloud()) { // override provisioning config set in shared props since isolation // is not yet supported for every pu type. final boolean dedicated = IsolationUtils.isDedicated(service); final CloudifyMachineProvisioningConfig config = createCloudifyMachineProvisioningConfig(); setIsolationConfig(deployment, dedicated, config); long cloudExternalProcessMemoryInMB; logger.info("setting deployment memory capacity for container according to isolation method"); if (dedicated) { cloudExternalProcessMemoryInMB = calculateExternalProcessMemory(); } else { cloudExternalProcessMemoryInMB = IsolationUtils.getInstanceMemoryMB(service); final long usmRequiredMemoryInMB = MemoryUnit.toMegaBytes( deploymentConfig.getCloud().getConfiguration().getComponents().getUsm().getMaxMemory()); if (usmRequiredMemoryInMB > cloudExternalProcessMemoryInMB) { throw new IllegalStateException("the usm required memory " + usmRequiredMemoryInMB + " can not be more then the total memory defined for a service instance " + cloudExternalProcessMemoryInMB); } } // this defines the total external memory for gsc and external process deployment.memoryCapacityPerContainer((int) cloudExternalProcessMemoryInMB, MemoryUnit.MEGABYTES); if (scalingRulesDefined) { try { final AutomaticCapacityScaleConfig scaleConfig = ElasticScaleConfigFactory .createAutomaticCapacityScaleConfig(deploymentConfig.getAbsolutePUName(), service, (int) cloudExternalProcessMemoryInMB, service.isLocationAware(), dedicated); deployment.scale(scaleConfig); } catch (final Exception e) { throw new ElasticDeploymentCreationException("Failed creating scale config.", e); } } else { final int totalMemoryInMB = (int) cloudExternalProcessMemoryInMB * deploymentConfig.getService().getNumInstances(); final double totalCpuCores = calculateTotalCpuCores(service); final ManualCapacityScaleConfig scaleConfig = ElasticScaleConfigFactory .createManualCapacityScaleConfig(totalMemoryInMB, totalCpuCores, service.isLocationAware(), dedicated); deployment.scale(scaleConfig); } } else { // localcloud // this defines the total external memory for gsc and external process final int externalProcessMemoryInMB = 512; deployment.memoryCapacityPerContainer(externalProcessMemoryInMB, MemoryUnit.MEGABYTES); if (scalingRulesDefined) { try { final AutomaticCapacityScaleConfig scaleConfig = ElasticScaleConfigFactory .createAutomaticCapacityScaleConfig(deploymentConfig.getAbsolutePUName(), service, externalProcessMemoryInMB, false, false); deployment.scale(scaleConfig); } catch (final Exception e) { throw new ElasticDeploymentCreationException("Failed creating scale config.", e); } } else { // the processing unit scales out whenever the specified memory capacity is breached deployment.scale(new ManualCapacityScaleConfigurer() .memoryCapacity(externalProcessMemoryInMB * deploymentConfig.getService().getNumInstances(), MemoryUnit.MEGABYTES).create()); } } return deployment; } private File createExpectedFile(final File packedFile) { final String packedFileName = packedFile.getName(); String fileType = ""; final String[] split = packedFileName.split("\\."); if (split.length > 1) { fileType = "." + split[split.length - 1]; } final String expectedName = this.deploymentConfig.getAbsolutePUName() + fileType; if (!packedFile.getName().equals(expectedName)) { final File renamedFile = new File(packedFile.getParentFile(), expectedName); if (renamedFile.exists()) { final boolean deleteResult = FileUtils.deleteQuietly(renamedFile); if (!deleteResult) { throw new IllegalStateException("Failed to delete file: " + renamedFile); } } if (!packedFile.renameTo(renamedFile)) { throw new IllegalStateException("Failed to rename " + packedFile.getAbsolutePath() + " to: " + renamedFile.getAbsolutePath()); } return renamedFile; } return packedFile; } private void prepareSla(final Sla sla) { if (isLocalcloud()) { return; } // Assuming one container per machine then container memory = // machine memory final int availableMemoryOnMachine = (int) calculateExternalProcessMemory(); if (sla.getMemoryCapacityPerContainer() != null && sla.getMemoryCapacityPerContainer() > availableMemoryOnMachine) { throw new IllegalStateException( "memoryCapacityPerContainer SLA is larger than available memory on machine\n" + sla.getMemoryCapacityPerContainer() + " > " + availableMemoryOnMachine); } if (sla.getMemoryCapacityPerContainer() == null) { sla.setMemoryCapacityPerContainer(availableMemoryOnMachine); } final int minimumNumberOfContainers = sla.getHighlyAvailable() ? 2 : 1; final int minMemoryInMB = minimumNumberOfContainers * sla.getMemoryCapacityPerContainer(); if (sla.getMemoryCapacity() == null || sla.getMemoryCapacity() < minMemoryInMB) { logger.info("Setting memoryCapacity for service " + deploymentConfig.getAbsolutePUName() + " to minimum " + minMemoryInMB + "MB"); sla.setMemoryCapacity(minMemoryInMB); } if (sla.getMaxMemoryCapacity() == null || sla.getMaxMemoryCapacity() < sla.getMemoryCapacity()) { logger.info("Setting maxMemoryCapacity for service " + deploymentConfig.getAbsolutePUName() + " to memoryCapacity " + sla.getMemoryCapacity() + "MB"); sla.setMaxMemoryCapacity(sla.getMemoryCapacity()); } } private void setLocalcloudMachineProvisioningConfig( final ElasticDeploymentTopology deployment) { final int reservedMemoryPerMachineInMB = 256; final int reservedMemoryPerManagementMachineInMB = 256; // All PUs on this role share the same machine. Machines // are identified by zone. final DiscoveredMachineProvisioningConfig config = new DiscoveredMachineProvisioningConfigurer() .reservedMemoryCapacityPerMachine(reservedMemoryPerMachineInMB, MemoryUnit.MEGABYTES) .create(); // localcloud is also the management machine config.setReservedMemoryCapacityPerManagementMachineInMB(reservedMemoryPerManagementMachineInMB); // TODO: This should be checked and removed. we no longer use zones. final String[] agentZones = new String[] { LOCALCLOUD_ZONE }; config.setGridServiceAgentZones(agentZones); deployment.publicMachineProvisioning(config); } CloudifyMachineProvisioningConfig createCloudifyMachineProvisioningConfig() { final Cloud cloud = deploymentConfig.getCloud(); final String serviceTemplateName = deploymentConfig.getTemplateName(); final String managementMachineTemplateName = cloud.getConfiguration().getManagementMachineTemplate(); final Map<String, ComputeTemplate> templates = cloud.getCloudCompute().getTemplates(); final ComputeTemplate serviceTemplate = templates.get(serviceTemplateName); final ComputeTemplate managementTemplate = templates.get(managementMachineTemplateName); String storageTemplate = null; if (deploymentConfig.getService().getStorage() != null) { storageTemplate = deploymentConfig.getService().getStorage().getTemplate(); logger.fine("Storage template " + storageTemplate + " is used with deployment"); } logger.fine("Creating cloud machine provisioning config. Template remote directory is: " + serviceTemplate.getRemoteDirectory()); // TODO: is there any reason for passing the remote dir? this could be extracted from the cloud file. final CloudifyMachineProvisioningConfig config = new CloudifyMachineProvisioningConfig( cloud, serviceTemplate, serviceTemplateName, managementTemplate.getRemoteDirectory(), storageTemplate); config.setAuthGroups(deploymentConfig.getAuthGroups()); final String cloudOverrides = deploymentConfig.getCloudOverrides(); if (cloudOverrides != null) { logger.fine("Recieved request for installation of " + deploymentConfig.getAbsolutePUName() + " with cloud overrides parameters [ " + cloudOverrides + "]"); config.setCloudOverridesPerService(cloudOverrides); } else { logger.fine("No cloud overrides parameters were requested for the installation of " + deploymentConfig.getAbsolutePUName()); } // TODO: When is this used? addCloudConfigurationCostants(config); config.setLocator(deploymentConfig.getLocators()); // adds the serialized network configuration to the config object addNetworkConfigurationToConfig(config); return config; } private void addNetworkConfigurationToConfig(final CloudifyMachineProvisioningConfig config) { if (this.deploymentConfig.getService().getNetwork() != null) { final ObjectMapper mapper = new ObjectMapper(); try { final String serializedNetwork = mapper.writeValueAsString(this.deploymentConfig.getService().getNetwork()); logger.info("Setting network string to: " + serializedNetwork); config.setNetworkAsString(serializedNetwork); } catch (final IOException e) { throw new IllegalArgumentException( "Failed to serialize service network description into a JSON string", e); } } } private void addCloudConfigurationCostants( final CloudifyMachineProvisioningConfig config) { final byte[] cloudConfig = deploymentConfig.getCloudConfig(); if (cloudConfig != null) { config.setServiceCloudConfiguration(cloudConfig); } } private boolean isLocalcloud() { if (deploymentConfig.getCloud() == null) { return true; } return false; } // This method is currently used only for USM type services. private void setIsolationConfig( final ElasticDeploymentTopology deployment, final boolean dedicated, final CloudifyMachineProvisioningConfig config) { final Service service = deploymentConfig.getService(); if (IsolationUtils.isUseManagement(service)) { config.setDedicatedManagementMachines(false); } else { config.setDedicatedManagementMachines(true); } if (dedicated) { // service deployment will have a dedicated agent per instance deployment.dedicatedMachineProvisioning(config); } else { // check what mode of isolation we should use if (IsolationUtils.isGlobal(service)) { logger.info("global mode is on. will use public machine provisioning for " + deploymentConfig.getAbsolutePUName() + " deployment."); logger.info("isolationSLA = " + service.getIsolationSLA()); // service instances can be deployed across all agents deployment.publicMachineProvisioning(config); } else if (IsolationUtils.isAppShared(service)) { final String applicationName = deploymentConfig.getApplicationName(); logger.info("app shared mode is on. will use shared machine provisioning for " + deploymentConfig.getAbsolutePUName() + " deployment. isolation id = " + applicationName); // service instances can be deployed across all agents with the correct isolation id deployment.sharedMachineProvisioning(applicationName, config); } else if (IsolationUtils.isTenantShared(service)) { final String authGroups = deploymentConfig.getAuthGroups(); if (authGroups == null) { throw new IllegalStateException("authGroups cannot be null when using tenant shared isolation"); } logger.info("tenant shared mode is on. will use shared machine provisioning for " + deploymentConfig.getAbsolutePUName() + " deployment. isolation id = " + authGroups); // service instances can be deployed across all agents with the correct isolation id deployment.sharedMachineProvisioning(authGroups, config); } if (IsolationUtils.isGlobal(service) && IsolationUtils.isUseManagement(service)) { final String managementMachineTemplateName = deploymentConfig.getCloud(). getConfiguration().getManagementMachineTemplate(); final ComputeDetails compute = service.getCompute(); if (compute != null) { if (compute.getTemplate() != null && !compute.getTemplate().isEmpty()) { if (!compute.getTemplate().equals(managementMachineTemplateName)) { // this is just a clarification log. // the service wont be installed on a management machine(even if there is enough memory) // because the management machine template does not match the desired template logger.warning("Installation of service " + service.getName() + " on a management machine " + "will not be attempted since the specified template(" + compute.getTemplate() + ")" + " is different than the management machine template(" + managementMachineTemplateName + ")"); } } } else { // normal default is to the first template. but when specified useManagement // do a silent default to the management machine template. deploymentConfig.setTemplateName(managementMachineTemplateName); } } } } private void setContextProperties( final ElasticDeploymentTopology deployment, final Properties contextProperties) { final Set<Entry<Object, Object>> contextPropsEntries = contextProperties .entrySet(); for (final Entry<Object, Object> entry : contextPropsEntries) { deployment.addContextProperty((String) entry.getKey(), (String) entry.getValue()); } } private static double calculateTotalCpuCores(final Service service) { final double instanceCpuCores = IsolationUtils.getInstanceCpuCores(service); final int numberOfInstances = service.getNumInstances(); return numberOfInstances * instanceCpuCores; } // calculate the external process memory according to the // properties set in the template and the reserved capacity for machine private long calculateExternalProcessMemory() { final String templateName = deploymentConfig.getTemplateName(); final Cloud cloud = deploymentConfig.getCloud(); final ComputeTemplate template = cloud.getCloudCompute().getTemplates().get(templateName); // TODO remove hardcoded number logger.fine("Calculating external proc mem for template: " + template); final int machineMemoryMB = template.getMachineMemoryMB(); final int reservedMemoryCapacityPerMachineInMB = cloud.getProvider() .getReservedMemoryCapacityPerMachineInMB(); final int safteyMargin = 100; // get rid of this constant. see // CLOUDIFY-297 long cloudExternalProcessMemoryInMB = machineMemoryMB - reservedMemoryCapacityPerMachineInMB - safteyMargin; if (cloudExternalProcessMemoryInMB <= 0) { throw new IllegalStateException("Cloud template machineMemoryMB (" + machineMemoryMB + "MB) must be bigger than " + "reservedMemoryCapacityPerMachineInMB+" + safteyMargin + " (" + (reservedMemoryCapacityPerMachineInMB + safteyMargin) + ")"); } logger.fine("template.machineMemoryMB = " + template.getMachineMemoryMB() + "MB\n" + "cloud.provider.reservedMemoryCapacityPerMachineInMB = " + reservedMemoryCapacityPerMachineInMB + "MB\n" + "cloudExternalProcessMemoryInMB = " + cloudExternalProcessMemoryInMB + "MB" + "cloudExternalProcessMemoryInMB = cloud.machineMemoryMB - " + "cloud.reservedMemoryCapacityPerMachineInMB" + " = " + cloudExternalProcessMemoryInMB); // USM can not require more memory then the maximum total memory available. final long usmRequiredMemoryInMB = MemoryUnit.toMegaBytes( cloud.getConfiguration().getComponents().getUsm().getMaxMemory()); cloudExternalProcessMemoryInMB = Math.max(cloudExternalProcessMemoryInMB, usmRequiredMemoryInMB); return cloudExternalProcessMemoryInMB; } /** * Create Properties object with settings from the service object, if found on the given service. The supported * settings are: com.gs.application.dependsOn com.gs.service.type com.gs.service.icon * com.gs.service.network.protocolDescription * * The service object the read the settings from * * @return Properties object populated with the above properties, if found on the given service. */ private Properties createServiceContextProperties() { final Properties contextProperties = new Properties(); contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_APPLICATION_NAME, deploymentConfig.getApplicationName()); contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_AUTH_GROUPS, deploymentConfig.getAuthGroups()); contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_DEPLOYMENT_ID, deploymentConfig.getDeploymentId()); if (deploymentConfig.getTemplateName() != null) { contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_TEMPLATE, deploymentConfig.getTemplateName()); } final Service service = deploymentConfig.getService(); final List<String> dependsOn = service.getDependsOn(); if (dependsOn.isEmpty()) { contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_DEPENDS_ON, "[]"); } else { final List<String> absoluteServiceNames = new ArrayList<String>(); for (final String name : dependsOn) { absoluteServiceNames.add(ServiceUtils.getAbsolutePUName( deploymentConfig.getApplicationName(), name.trim())); } contextProperties.setProperty( CloudifyConstants.CONTEXT_PROPERTY_DEPENDS_ON, Arrays.toString(absoluteServiceNames.toArray())); } if (service.getType() != null) { contextProperties.setProperty( CloudifyConstants.CONTEXT_PROPERTY_SERVICE_TYPE, service.getType()); } if (service.getIcon() != null) { contextProperties.setProperty( CloudifyConstants.CONTEXT_PROPERTY_SERVICE_ICON, CloudifyConstants.SERVICE_EXTERNAL_FOLDER + service.getIcon()); } if (service.getNetwork() != null) { if (service.getNetwork().getProtocolDescription() != null) { contextProperties .setProperty( CloudifyConstants.CONTEXT_PROPERTY_NETWORK_PROTOCOL_DESCRIPTION, service.getNetwork().getProtocolDescription()); } } final String cloudName = getCloudName(); contextProperties.setProperty( CloudifyConstants.CONTEXT_PROPERTY_CLOUD_NAME, cloudName); contextProperties.setProperty( CloudifyConstants.CONTEXT_PROPERTY_ELASTIC, Boolean.toString(service.isElastic())); final InstallServiceRequest installRequest = deploymentConfig.getInstallRequest(); if (installRequest.isDebugAll()) { contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_DEBUG_ALL, Boolean.TRUE.toString()); contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_DEBUG_MODE, installRequest.getDebugMode()); } else if (installRequest.getDebugEvents() != null) { contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_DEBUG_EVENTS, installRequest.getDebugEvents()); contextProperties.setProperty(CloudifyConstants.CONTEXT_PROPERTY_DEBUG_MODE, installRequest.getDebugMode()); } return contextProperties; } private String getCloudName() { if (deploymentConfig.getCloud() != null) { return deploymentConfig.getCloud().getName(); } else { return CloudifyConstants.LOCAL_CLOUD_NAME; } } // adds all shared properties among all deployment types private void addSharedDeploymentParameters( final ElasticDeploymentTopology deployment) { deployment.name(deploymentConfig.getAbsolutePUName()); // add context properties final Properties contextProperties = createServiceContextProperties(); setContextProperties(deployment, contextProperties); if (!isLocalcloud()) { logger.fine("setting lrmi bind ports and container memory context properties"); deployment.addCommandLineArgument("-D" + CloudifyConstants.LRMI_BIND_PORT_CONTEXT_PROPERTY + "=" + deploymentConfig.getCloud().getConfiguration().getComponents().getUsm().getPortRange()) .addCommandLineArgument("-Xmx" + deploymentConfig.getCloud().getConfiguration().getComponents() .getUsm().getMaxMemory()) .addCommandLineArgument("-Xms" + deploymentConfig.getCloud().getConfiguration().getComponents() .getUsm().getMinMemory()); final CloudifyMachineProvisioningConfig config = createCloudifyMachineProvisioningConfig(); // TODO: uncomment this when isolation is defined for pu types. // isolation should work out of the box for every pu type. // setIsolationConfig(deployment, dedicated, config); deployment.dedicatedMachineProvisioning(config); } else { // localcloud setLocalcloudMachineProvisioningConfig(deployment); } } }