/*******************************************************************************
* Copyright (c) 2011 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.esc.driver.provisioning;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.cloudifysource.domain.cloud.Cloud;
import org.cloudifysource.domain.cloud.FileTransferModes;
import org.cloudifysource.domain.cloud.compute.ComputeTemplate;
import org.cloudifysource.dsl.internal.CloudifyConstants;
import org.openspaces.admin.pu.elastic.ElasticMachineProvisioningConfig;
import org.openspaces.admin.zone.config.AnyZonesConfig;
import org.openspaces.admin.zone.config.AtLeastOneZoneConfigurer;
import org.openspaces.admin.zone.config.ZonesConfig;
import org.openspaces.core.util.StringProperties;
import org.openspaces.grid.gsm.capacity.CapacityRequirement;
import org.openspaces.grid.gsm.capacity.CapacityRequirements;
import org.openspaces.grid.gsm.capacity.CpuCapacityRequirement;
import org.openspaces.grid.gsm.capacity.DriveCapacityRequirement;
import org.openspaces.grid.gsm.capacity.MemoryCapacityRequirement;
/************
* Cloud Provisioning configuration.
*
* @author barakme
* @since 2.0
*
*/
public class CloudifyMachineProvisioningConfig implements ElasticMachineProvisioningConfig {
private static final String COLON_CHAR = ":";
private static final String REMOTE_ADMIN_SHARE_CHAR = "$";
private static final String BACK_SLASH = "\\";
private static final String FORWARD_SLASH = "/";
private static final double NUMBER_OF_CPU_CORES_PER_MACHINE_DEFAULT = 4;
private static final String NUMBER_OF_CPU_CORES_PER_MACHINE_KEY = "number-of-cpu-cores-per-machine";
private static final String ZONES_KEY = "zones";
private static final String ZONES_SEPARATOR = ",";
private static final String[] ZONES_DEFAULT = new String[] {}; // empty zone by default
private static final boolean DEDICATED_MANAGEMENT_MACHINES_DEFAULT = false;
private static final String DEDICATED_MANAGEMENT_MACHINES_KEY = "dedicated-management-machines";
private static final String RESERVED_MEMORY_CAPACITY_PER_MACHINE_MEGABYTES_KEY =
"reserved-memory-capacity-per-machine-megabytes";
private static final String RESERVED_MEMORY_CAPACITY_PER_MANAGEMENT_MACHINE_MEGABYTES_KEY =
"reserved-memory-capacity-per-management-machine-megabytes";
private static final long RESERVED_MEMORY_CAPACITY_PER_MACHINE_MEGABYTES_DEFAULT = 256;
private static final long RESERVED_MEMORY_CAPACITY_PER_MANAGEMENT_MACHINE_MEGABYTES_DEFAULT = 512;
private static final String RESERVED_CPU_PER_MACHINE_KEY = "reserved-cpu-cores-per-machine";
private static final double RESERVED_CPU_PER_MACHINE_DEFAULT = 0.0;
private static final String RESREVED_DRIVES_CAPACITY_MEGABYTES_PER_MACHINE_KEY =
"resereved-drives-capacity-per-machine-megabytes";
private static final Map<String, String> RESERVED_DRIVES_CAPACITY_PER_MACHINE_DEFAULT =
new HashMap<String, String>();
private static final String RESREVED_DRIVES_CAPACITY_MEGABYTES_PER_MACHINE_KEY_VALUE_SEPERATOR = "=";
private static final String RESREVED_DRIVES_CAPACITY_MEGABYTES_PER_MACHINE_PAIR_SEPERATOR = ",";
private static final String LOCATOR_KEY = "locator";
private static final String SERVICE_CLOUD_CONFIGURATION_KEY = "SERVICE_CLOUD_CONFIGURATION_KEY";
private static final String AUTH_GROUPS_DEFAULT = null;
private static final String AUTH_GROUPS_KEY = "auth-groups";
private static final String STORAGE_TEMPLATE_NAME = "storage-template-name";
private static final String SERVICE_NETWORK_STRING_KEY = "SERVICE_NETWORK_STRING_KEY";
private StringProperties properties = new StringProperties(new HashMap<String, String>());
/**
*
* @param cloud
* .
* @param template
* .
* @param cloudTemplateName
* .
* @param managementTemplateRemoteDirectory
* .
* @param management
* - true if the deployment
*/
public CloudifyMachineProvisioningConfig(final Cloud cloud, final ComputeTemplate template,
final String cloudTemplateName, final String managementTemplateRemoteDirectory,
final String storageTemplateName) {
if (!StringUtils.isEmpty(storageTemplateName)) {
setStorageTemplateName(storageTemplateName);
}
setMinimumNumberOfCpuCoresPerMachine(template.getNumberOfCores());
setReservedMemoryCapacityPerMachineInMB(cloud.getProvider().getReservedMemoryCapacityPerMachineInMB());
setReservedMemoryCapacityPerManagementMachineInMB(cloud.getProvider()
.getReservedMemoryCapacityPerManagementMachineInMB());
String remoteDir = managementTemplateRemoteDirectory;
logger.log(Level.FINE, "Original remote directory is: " + remoteDir);
if (template.getFileTransfer() == FileTransferModes.CIFS) {
logger.log(Level.FINE, "Running on windows, modifying remote directory config. Original was: " + remoteDir);
remoteDir = getWindowsRemoteDirPath(managementTemplateRemoteDirectory);
}
else {
remoteDir = template.getRemoteDirectory();
}
logger.log(Level.INFO, "Setting cloud configuration directory to: " + remoteDir);
setCloudConfigurationDirectory(remoteDir);
setCloudTemplateName(cloudTemplateName);
}
private void setStorageTemplateName(final String storageTemplateName) {
this.properties.put(STORAGE_TEMPLATE_NAME, storageTemplateName);
}
public String getStorageTemplateName() {
return this.properties.get(STORAGE_TEMPLATE_NAME);
}
private String getWindowsRemoteDirPath(String remoteDirectory) {
String homeDirectoryName = remoteDirectory;
homeDirectoryName = homeDirectoryName.replace(REMOTE_ADMIN_SHARE_CHAR, "");
if (homeDirectoryName.startsWith(FORWARD_SLASH)) {
homeDirectoryName = homeDirectoryName.substring(1);
}
if (homeDirectoryName.charAt(1) == FORWARD_SLASH.charAt(0)) {
homeDirectoryName = homeDirectoryName.substring(0, 1) + COLON_CHAR + homeDirectoryName.substring(1);
}
homeDirectoryName = homeDirectoryName.replace(FORWARD_SLASH, BACK_SLASH);
return homeDirectoryName;
}
private java.util.logging.Logger logger = java.util.logging.Logger.getLogger(CloudifyMachineProvisioningConfig.class.getName());
/**************
* .
*
* @param properties
* .
*/
public CloudifyMachineProvisioningConfig(final Map<String, String> properties) {
this.properties = new StringProperties(properties);
}
@Override
public String getBeanClassName() {
return "org.cloudifysource.esc.driver.provisioning.ElasticMachineProvisioningCloudifyAdapter";
}
@Override
public void setProperties(final Map<String, String> properties) {
this.properties = new StringProperties(properties);
}
@Override
public Map<String, String> getProperties() {
return this.properties.getProperties();
}
@Override
public double getMinimumNumberOfCpuCoresPerMachine() {
return properties.getDouble(
NUMBER_OF_CPU_CORES_PER_MACHINE_KEY, NUMBER_OF_CPU_CORES_PER_MACHINE_DEFAULT);
}
/**********
* Setter.
*
* @param minimumCpuCoresPerMachine
* .
*/
public final void setMinimumNumberOfCpuCoresPerMachine(final double minimumCpuCoresPerMachine) {
properties.putDouble(
NUMBER_OF_CPU_CORES_PER_MACHINE_KEY, minimumCpuCoresPerMachine);
}
/**
*
* @param cloudOverrides
* a string representation of cloudify overrides.
*/
public final void setCloudOverridesPerService(final String cloudOverrides) {
properties.put(CloudifyConstants.ELASTIC_PROPERTIES_CLOUD_OVERRIDES_PER_SERVICE, cloudOverrides);
}
/**
*
* @param cloudOverrides
* .
* @throws IOException
*/
public final void setCloudOverridesPerService(final File cloudOverrides) throws IOException {
properties.put(CloudifyConstants.ELASTIC_PROPERTIES_CLOUD_OVERRIDES_PER_SERVICE,
FileUtils.readFileToString(cloudOverrides));
}
public String getCloudOverridesPerService() {
return properties.get(CloudifyConstants.ELASTIC_PROPERTIES_CLOUD_OVERRIDES_PER_SERVICE, "");
}
public String getCloudTemplateName() {
return properties.get(CloudifyConstants.ELASTIC_PROPERTIES_CLOUD_TEMPLATE_NAME);
}
/***************
* Setter.
*
* @param cloudTemplateName
* .
*/
public final void setCloudTemplateName(final String cloudTemplateName) {
properties.put(
CloudifyConstants.ELASTIC_PROPERTIES_CLOUD_TEMPLATE_NAME, cloudTemplateName);
}
public String getCloudConfigurationDirectory() {
return properties.get(CloudifyConstants.ELASTIC_PROPERTIES_CLOUD_CONFIGURATION_DIRECTORY);
}
/***************
* Setter.
*
* @param cloudConfigurationDirectory
* .
*/
public final void setCloudConfigurationDirectory(final String cloudConfigurationDirectory) {
properties.put(
CloudifyConstants.ELASTIC_PROPERTIES_CLOUD_CONFIGURATION_DIRECTORY, cloudConfigurationDirectory);
}
@Override
public CapacityRequirements getReservedCapacityPerMachine() {
final List<CapacityRequirement> requirements = createReservedCapacityPerMachine(false);
CapacityRequirements capacityRequirements =
new CapacityRequirements(requirements.toArray(new CapacityRequirement[requirements.size()]));
return capacityRequirements;
}
@Override
public CapacityRequirements getReservedCapacityPerManagementMachine() {
final List<CapacityRequirement> requirements = createReservedCapacityPerMachine(true);
CapacityRequirements capacityRequirements =
new CapacityRequirements(requirements.toArray(new CapacityRequirement[requirements.size()]));
return capacityRequirements;
}
/**********
* .
*
* @return .
*/
public Map<String, Long> getReservedDriveCapacityPerMachineInMB() {
final Map<String, String> reserved =
this.properties.getKeyValuePairs(
RESREVED_DRIVES_CAPACITY_MEGABYTES_PER_MACHINE_KEY,
RESREVED_DRIVES_CAPACITY_MEGABYTES_PER_MACHINE_PAIR_SEPERATOR,
RESREVED_DRIVES_CAPACITY_MEGABYTES_PER_MACHINE_KEY_VALUE_SEPERATOR,
RESERVED_DRIVES_CAPACITY_PER_MACHINE_DEFAULT);
final Map<String, Long> reservedInMB = new HashMap<String, Long>();
for (final Map.Entry<String, String> entry : reserved.entrySet()) {
final String drive = entry.getKey();
reservedInMB.put(
drive, Long.valueOf(entry.getValue()));
}
return reservedInMB;
}
/**********
* Setter.
*
* @param reservedCpu
* .
*/
public void setReservedCpuCapacityPerMachineInMB(final double reservedCpu) {
this.properties.putDouble(
RESERVED_CPU_PER_MACHINE_KEY, reservedCpu);
}
public double getReservedCpuCapacityPerMachine() {
return this.properties.getDouble(
RESERVED_CPU_PER_MACHINE_KEY, RESERVED_CPU_PER_MACHINE_DEFAULT);
}
public long getReservedMemoryCapacityPerMachineInMB() {
return this.properties.getLong(
RESERVED_MEMORY_CAPACITY_PER_MACHINE_MEGABYTES_KEY,
RESERVED_MEMORY_CAPACITY_PER_MACHINE_MEGABYTES_DEFAULT);
}
private Long getReservedMemoryCapacityPerManagementMachineInMB() {
return this.properties.getLong(
RESERVED_MEMORY_CAPACITY_PER_MANAGEMENT_MACHINE_MEGABYTES_KEY,
RESERVED_MEMORY_CAPACITY_PER_MANAGEMENT_MACHINE_MEGABYTES_DEFAULT);
}
/*************
* Setter.
*
* @param reservedInMB
* .
*/
public final void setReservedMemoryCapacityPerMachineInMB(final long reservedInMB) {
this.properties.putLong(
RESERVED_MEMORY_CAPACITY_PER_MACHINE_MEGABYTES_KEY, reservedInMB);
}
/*************
* Setter.
*
* @param reservedInMB
* .
*/
public final void setReservedMemoryCapacityPerManagementMachineInMB(
final int reservedInMB) {
this.properties.putLong(
RESERVED_MEMORY_CAPACITY_PER_MANAGEMENT_MACHINE_MEGABYTES_KEY, reservedInMB);
}
@Override
public ZonesConfig getGridServiceAgentZones() {
final String[] zones = properties.getArray(
ZONES_KEY, ZONES_SEPARATOR, ZONES_DEFAULT);
if (zones.length == 0) {
// this is ok, since a pu without any zone CAN be deployed on any agent
return new AnyZonesConfig();
}
return new AtLeastOneZoneConfigurer().addZones(zones).create();
}
/************
* Setter.
*
* @param zones
* .
*/
public void setGridServiceAgentZones(final String[] zones) {
this.properties.putArray(
ZONES_KEY, zones, ZONES_SEPARATOR);
}
@Override
public boolean isDedicatedManagementMachines() {
return properties.getBoolean(
DEDICATED_MANAGEMENT_MACHINES_KEY, DEDICATED_MANAGEMENT_MACHINES_DEFAULT);
}
/************
* Setter.
*
* @param value
* .
*/
public void setDedicatedManagementMachines(final boolean value) {
properties.putBoolean(
DEDICATED_MANAGEMENT_MACHINES_KEY, value);
}
@Override
public boolean isGridServiceAgentZoneMandatory() {
return false;
}
/***********
* Setter.
*
* @param locator
* .
*/
public void setLocator(final String locator) {
properties.put(
LOCATOR_KEY, locator);
}
public String getLocator() {
return properties.get(LOCATOR_KEY);
}
/************
* Setter.
*
* @param serviceCloudConfiguration
* .
*/
public void setServiceCloudConfiguration(final byte[] serviceCloudConfiguration) {
final String encodedResult = Base64.encodeBase64String(serviceCloudConfiguration);
properties.put(SERVICE_CLOUD_CONFIGURATION_KEY, encodedResult);
}
/**********
* Getter.
*
* @return .
*/
public byte[] getServiceCloudConfiguration() {
final String encodedFile = properties.get(SERVICE_CLOUD_CONFIGURATION_KEY);
if (encodedFile == null) {
return null;
}
final byte[] decodedFile = Base64.decodeBase64(encodedFile);
return decodedFile;
}
public void setAuthGroups(String authGroups) {
properties.putStringWrapperObject(AUTH_GROUPS_KEY, authGroups);
}
public String getAuthGroups() {
return (String) properties.getStringWrapperObject(AUTH_GROUPS_KEY, AUTH_GROUPS_DEFAULT);
}
private List<CapacityRequirement> createReservedCapacityPerMachine(final boolean management) {
final List<CapacityRequirement> requirements = new ArrayList<CapacityRequirement>();
if (management) {
requirements.add(new MemoryCapacityRequirement(getReservedMemoryCapacityPerManagementMachineInMB()));
} else {
requirements.add(new MemoryCapacityRequirement(getReservedMemoryCapacityPerMachineInMB()));
}
requirements.add(new CpuCapacityRequirement(getReservedCpuCapacityPerMachine()));
final Map<String, Long> reservedDriveCapacity = getReservedDriveCapacityPerMachineInMB();
for (final Entry<String, Long> entry : reservedDriveCapacity.entrySet()) {
final String drive = entry.getKey();
requirements.add(new DriveCapacityRequirement(drive, entry.getValue()));
}
return requirements;
}
public String getNetworkAsString() {
return properties.get(SERVICE_NETWORK_STRING_KEY);
}
/********
* Sets the serialized service network description.
* @param networkAsString the serialized network description.
*/
public void setNetworkAsString(final String networkAsString) {
properties.put(SERVICE_NETWORK_STRING_KEY, networkAsString);
}
}