/*
* Copyright (C) 2008 Universidade Federal de Campina Grande
*
* This file is part of OurGrid.
*
* OurGrid is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.ourgrid.common.executor;
import java.io.File;
import java.util.Map;
import org.ourgrid.common.executor.config.ExecutorConfiguration;
import org.ourgrid.common.executor.config.GatewayExecutorConfiguration;
import org.ourgrid.common.executor.config.GenericExecutorConfiguration;
import org.ourgrid.common.executor.config.VMWareExecutorConfiguration;
import org.ourgrid.common.executor.config.VServerExecutorConfiguration;
import org.ourgrid.common.executor.config.VirtualMachineExecutorConfiguration;
import org.ourgrid.common.executor.gateway.GatewayExecutor;
import org.ourgrid.common.executor.generic.GenericExecutor;
import org.ourgrid.common.executor.vbox.VirtualBoxEnvironment;
import org.ourgrid.common.executor.vmware.VMWareSandBoxEnvironment;
import org.ourgrid.common.executor.vserver.VServerSandBoxedEnvironment;
import org.ourgrid.common.util.CommonUtils;
import org.ourgrid.common.util.OS;
import org.ourgrid.worker.WorkerConfiguration;
import org.ourgrid.worker.business.messages.WorkerControllerMessages;
import br.edu.ufcg.lsd.commune.ModuleProperties;
import br.edu.ufcg.lsd.commune.container.logging.CommuneLogger;
import br.edu.ufcg.lsd.commune.context.ModuleContext;
/**
* This class is responsible for obtaining an Executor instance according to the
* Operating System being used.
*/
public class ExecutorFactory {
// Enumeration representing the kind of SandboxedExecutor for the machine
public enum SandboxedExecutorType {SWAN, VSERVER, VBOX, VMWARE, GATEWAY, GENERIC};
private ModuleContext context;
private final CommuneLogger logger;
/**
* @param logger the logger object to keep the information about the operations in the execution
*/
public ExecutorFactory(CommuneLogger logger) {
this(null, logger);
}
/**
* @param context the ModuleContext which will be used to set the properties of the virtual machine
* @param logger the logger object to keep the information about the operations in the execution
*/
public ExecutorFactory(ModuleContext context, CommuneLogger logger) {
this.context = context;
this.logger = logger;
}
/**
* Chooses and returns the kind of executor which will be used for the execution according
* to the Executor_Type property contained in the context. The executor can be a Sandboxed
* Environment (using virtualization) or a Native Executor (without virtualization).
* @return the correct Executor for the execution
*/
public Executor buildExecutor() {
if (context == null) {
logger.warn(WorkerControllerMessages.getBuildExecutorWithoutContextMessage());
return null;
}
String sandBoxTypeStr = context.getProperty(WorkerConfiguration.PROP_EXECUTOR_TYPE);
if (sandBoxTypeStr == null || sandBoxTypeStr.equals("OS")) {
return buildNewNativeExecutor();
}
SandboxedExecutorType sandBoxType = SandboxedExecutorType.valueOf(sandBoxTypeStr);
if (sandBoxType != null) {
return buildNewSandboxedExecutor(sandBoxType);
}
return buildNewNativeExecutor();
}
/**
* This is a factory method that returns a Executor depending on the
* platform the software is running.
*
* @param type The type of the executor.
*
* @return A concrete implementation of Executor depending on the OS
*/
private Executor buildNewSandboxedExecutor(SandboxedExecutorType type) {
Executor instance = null;
ExecutorConfiguration executorConfig = null;
switch (type) {
case SWAN:
instance = new SWANExecutor(logger);
break;
case VSERVER:
if (!OS.isFamilyUnix()) {
throw new ExecutorFactoryException("Unable to build new executor: VSERVER executor only works on Linux OS");
}
executorConfig = new VServerExecutorConfiguration(new File(context.getProperty(ModuleProperties.PROP_CONFDIR)));
instance = new SandboxedExecutor(new VServerSandBoxedEnvironment(logger));
break;
case VMWARE:
executorConfig = new VMWareExecutorConfiguration(new File(context.getProperty(ModuleProperties.PROP_CONFDIR)));
instance = new SandboxedExecutor(new VMWareSandBoxEnvironment(logger));
break;
case VBOX:
if (!(OS.isFamilyWin9x() || OS.isFamilyWindows() || OS.isFamilyDOS())) {
throw new ExecutorFactoryException("Unable to build new executor: VBOX executor only works on Windows OS");
}
executorConfig = new VirtualMachineExecutorConfiguration(new File(context.getProperty(ModuleProperties.PROP_CONFDIR)));
instance = new SandboxedExecutor(new VirtualBoxEnvironment(logger));
break;
case GATEWAY:
executorConfig = new GatewayExecutorConfiguration(new File(context.getProperty(ModuleProperties.PROP_CONFDIR)));
instance = new GatewayExecutor(logger);
break;
case GENERIC:
executorConfig = new GenericExecutorConfiguration(new File(context.getProperty(ModuleProperties.PROP_CONFDIR)));
// instance = new SandboxedExecutor(new GenericSandBoxEnvironment(logger));
instance = new GenericExecutor(logger);
break;
default:
throw new ExecutorFactoryException("Unable to build new executor: Executor " + type + " don't exists");
}
//Creating Properties
if (executorConfig != null) {
loadProperties(executorConfig);
}
instance.setConfiguration(executorConfig);
return instance;
}
// Sets in a new map the properties contained in the ExecutorConfiguration object
// or in the ModuleContext, prioritizing the ModuleContext properties. The name
// of the property is set as the key and the property itself as the value in the map.
private void loadProperties(ExecutorConfiguration executorConfiguration) {
Map<String, String> properties = CommonUtils.createSerializableMap();
if (executorConfiguration != null) {
for(String custom : executorConfiguration.getDefaultPropertiesNames()) {
String executorConfigurationProperty = executorConfiguration.getProperty( custom );
String configurationBasedProperty = context.getProperty( custom );
properties.put(custom, (configurationBasedProperty != null) ? configurationBasedProperty : executorConfigurationProperty);
}
}
executorConfiguration.loadCustomProperty(properties);
}
/**
* Creates a native OS executor, without virtualization.
*
* @return Returns the executor.
*/
public Executor buildNewNativeExecutor() {
Executor instance = null;
if (OS.isFamilyUnix()) {
instance = new LinuxExecutor(logger);
} else if (OS.isFamilyWin9x() || OS.isFamilyWindows() || OS.isFamilyDOS()) {
instance = new Win32Executor(logger);
} else {
throw new ExecutorFactoryException("Unable to build new executor, OS " + System.getProperty("os.name") + " is unsupported");
}
return instance;
}
}