package hudson.plugins.vmware;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import hudson.Extension;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.Resource;
import hudson.model.ResourceActivity;
import hudson.model.ResourceList;
import hudson.model.Result;
import hudson.plugins.vmware.vix.VixHostConfig;
import hudson.plugins.vmware.vix.VixVirtualComputer;
import hudson.plugins.vmware.vix.VixHost;
import hudson.plugins.vmware.vix.VixLibraryManager;
import hudson.plugins.vmware.vix.VixVirtualComputerConfig;
import hudson.tasks.BuildWrapper;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* Created by IntelliJ IDEA.
*
* @author Stephen Connolly
* @since 26-Sep-2007 16:06:28
*/
public class VMwareActivationWrapper extends BuildWrapper implements ResourceActivity {
public transient String vixLibraryPath;
public transient String hostName;
public transient String username;
public transient String password;
public transient int portNumber;
public transient boolean suspend;
public transient boolean waitForTools;
public transient boolean revert;
public transient String configFile;
private List<VMActivationConfig> machines;
private void importOldConfig() {
assert machines == null;
machines = new ArrayList<VMActivationConfig>();
VixHostConfig hostConfig = null;
if (vixLibraryPath != null) {
// pull legacy config
hostConfig =
new VixHostConfig(vixLibraryPath, hostName, portNumber, HostType.VMWARE_SERVER, username, password);
boolean found = false;
for (VixHostConfig h : DESCRIPTOR.getHosts()) {
if (h.equals(hostConfig)) {
found = true;
hostConfig = h;
break;
}
}
if (!found) {
hostConfig = new VixHostConfig(
hostConfig.getUsername() + "@" + hostConfig.getHostType() + ":" + hostConfig
.getPortNumber(), vixLibraryPath, hostName, portNumber, HostType.VMWARE_SERVER,
username,
password);
DESCRIPTOR.addHost(hostConfig);
}
}
if (hostConfig == null) {
hostConfig = DESCRIPTOR.getHosts().get(0);
}
if (configFile != null && !"".equals(configFile)) {
final VMWrapperPowerUpMode powerUpMode;
if (waitForTools) {
powerUpMode = revert ? VMWrapperPowerUpMode.REVERT_WAIT : VMWrapperPowerUpMode.NORMAL_WAIT;
} else {
powerUpMode = revert ? VMWrapperPowerUpMode.REVERT : VMWrapperPowerUpMode.NORMAL;
}
final VMWrapperPowerDownMode powerDownMode =
suspend ? VMWrapperPowerDownMode.SUSPEND : VMWrapperPowerDownMode.NORMAL;
machines.add(new VMActivationConfig(
powerUpMode,
powerDownMode,
0,
false,
null,
0,
new VixVirtualComputerConfig(configFile, hostConfig)
));
}
}
public List<VMActivationConfig> getMachines() {
if (machines == null) {
importOldConfig();
}
return machines;
}
public void setMachines(List<VMActivationConfig> machines) {
this.machines = machines;
}
@Override
public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener buildListener)
throws IOException, InterruptedException {
final class VMC {
private final VixVirtualComputer vm;
private final VixHost host;
private long powerTime;
private final VMActivationConfig cfg;
public VMC(VixVirtualComputer vm, VixHost host, VMActivationConfig cfg) {
this.vm = vm;
this.host = host;
this.powerTime = powerTime; //XXX this does nothing
this.cfg = cfg;
}
public void prepareFeedback(BuildListener listener) {
if (cfg.isWaitForFeedback()) {
listener.getLogger().println(Messages.VMwareActivationWrapper_LogFeedbackPrepare(
cfg.getFeedbackKey(), cfg.toString()));
PluginImpl.clearVMIP(cfg.getFeedbackKey());
PluginImpl.watchVMIP(cfg.getFeedbackKey());
}
}
public boolean awaitFeedback(BuildListener listener) {
if (cfg.isWaitForFeedback()) {
listener.getLogger().println(Messages.VMwareActivationWrapper_LogFeedbackStartWait(
cfg.getFeedbackKey(), cfg));
try {
final boolean result = PluginImpl.awaitVMIP(cfg.getFeedbackKey(),
cfg.getFeedbackTimeout(), TimeUnit.SECONDS);
if (result) {
listener.getLogger().println(Messages.VMwareActivationWrapper_LogFeedbackResult(
cfg.getFeedbackKey(), PluginImpl.getVMIP(cfg.getFeedbackKey())));
} else {
listener.getLogger().println(Messages.VMwareActivationWrapper_LogTimedOut());
}
return result;
} catch (InterruptedException e) {
listener.getLogger().println(Messages.VMwareActivationWrapper_LogInterrupted());
e.printStackTrace(listener.getLogger());
return false;
}
}
return true;
}
public void powerUp(BuildListener listener) {
listener.getLogger()
.println(Messages.VMwareActivationWrapper_LogPreBuildStarted(cfg));
switch (cfg.getPowerUpMode()) {
case NOTHING:
break;
case REVERT:
case REVERT_WAIT:
listener.getLogger().println(Messages.VMwareActivationWrapper_LogRevertingVM());
vm.revertToSnapshot();
case NORMAL:
case NORMAL_WAIT:
listener.getLogger().println(Messages.VMwareActivationWrapper_LogPoweringUpVM());
vm.powerOn();
break;
default:
break;
}
switch (cfg.getPowerUpMode()) {
case NORMAL_WAIT:
case REVERT_WAIT:
listener.getLogger()
.println(Messages.VMwareActivationWrapper_LogWaitingForToolsStartup());
vm.waitForToolsInGuest(cfg.waitTimeout);
break;
default:
break;
}
powerTime = System.currentTimeMillis();
listener.getLogger().println(Messages.VMwareActivationWrapper_LogPrebuildCompleted(cfg));
}
public void powerDown(BuildListener buildListener) {
buildListener.getLogger()
.println(Messages.VMwareActivationWrapper_LogPostBuildActionsStarting(cfg));
while (System.currentTimeMillis() < powerTime + 10000L) {
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogWaitingForBIOSBoot());
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
// ignore
}
}
switch (cfg.getPowerDownMode()) {
case CREATE_POWER_OFF:
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogTakingSnapshot());
vm.createSnapshot("", "", true);
break;
case NOTHING:
case NORMAL:
case SUSPEND:
case CREATE_SUSPEND:
case CREATE_NORMAL:
default:
break;
}
switch (cfg.getPowerDownMode()) {
case SUSPEND:
case CREATE_SUSPEND:
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogSuspending());
vm.suspend();
break;
case NORMAL:
case CREATE_POWER_OFF:
case CREATE_NORMAL:
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogPoweringOff());
vm.powerOff();
break;
case NOTHING:
default:
break;
}
switch (cfg.getPowerDownMode()) {
case CREATE_SUSPEND:
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogTakingSnapshot());
vm.createSnapshot("", "", true);
break;
case CREATE_NORMAL:
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogTakingSnapshot());
vm.createSnapshot("", "", false);
break;
case NOTHING:
case NORMAL:
case SUSPEND:
case CREATE_POWER_OFF:
default:
break;
}
vm.close();
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogDisconnecting());
host.disconnect();
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogDone());
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogPostBuildActionsComplete(cfg));
}
}
class EnvironmentImpl extends Environment {
private final List<VMC> vms;
public EnvironmentImpl(List<VMC> vms) {
this.vms = vms;
}
@Override
public boolean tearDown(AbstractBuild build, BuildListener buildListener) throws IOException, InterruptedException {
for (VMC vm : vms) {
vm.powerDown(buildListener);
}
return true;
}
@Override
public void buildEnvVars(Map<String, String> map) {
super.buildEnvVars(map);
for (String key : PluginImpl.getVMs()) {
map.put(key, PluginImpl.getVMIP(key));
}
}
}
List<VMC> vms = new ArrayList<VMC>();
try {
for (VMActivationConfig machine : machines) {
final VixHostConfig config = machine.getConfig().getHost();
buildListener.getLogger()
.println(Messages.VMwareActivationWrapper_LogOpeningVixConnection(config.toPseudoUri()));
VixHost host = VixLibraryManager.getHostInstance(config);
try {
buildListener.getLogger().println(
Messages.VMwareActivationWrapper_LogOpeningVirtualMachine(machine));
VixVirtualComputer vm = host.open(machine.getConfig());
try {
final VMC vmc = new VMC(vm, host, machine);
vmc.prepareFeedback(buildListener);
vmc.powerUp(buildListener);
vms.add(vmc);
} catch (VMwareRuntimeException e) {
vm.close();
throw e;
}
} catch (VMwareRuntimeException e) {
host.disconnect();
throw e;
}
}
} catch (VMwareRuntimeException e) {
buildListener.getLogger().println(Messages.VMwareActivationWrapper_LogVixError(e.getMessage()));
e.printStackTrace(buildListener.getLogger());
build.setResult(Result.FAILURE);
for (VMC vmc : vms) {
vmc.powerDown(buildListener);
}
return null;
}
for (VMC vmc : vms) {
if (!vmc.awaitFeedback(buildListener)) {
build.setResult(Result.FAILURE);
for (VMC vmc2 : vms) {
vmc2.powerDown(buildListener);
}
return null;
}
}
return new EnvironmentImpl(vms);
}
@Override
public Descriptor<BuildWrapper> getDescriptor() {
return DESCRIPTOR;
}
@Extension
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
public ResourceList getResourceList() {
ResourceList resources = new ResourceList();
for (VMActivationConfig machine : machines) {
resources.w(new Resource(machine.toString()));
}
return resources;
}
public String getDisplayName() {
return DESCRIPTOR.getDisplayName();
}
public static final class DescriptorImpl extends Descriptor<BuildWrapper> {
private List<VixHostConfig> hosts;
DescriptorImpl() {
super(VMwareActivationWrapper.class);
load();
}
public String getDisplayName() {
return Messages.VMwareActivationWrapper_DescriptorImpl_DisplayName();
}
@Override
public VMwareActivationWrapper newInstance(StaplerRequest req, JSONObject formData) throws FormException {
VMwareActivationWrapper w = new VMwareActivationWrapper();
req.bindParameters(w, "vmware-activation.");
w.setMachines(req.bindParametersToList(VMActivationConfig.class, "vmware-activation.machine."));
return w;
}
@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindParameters(this, "vmware.");
hosts = req.bindParametersToList(VixHostConfig.class, "vmware.host.");
save();
return super.configure(req, formData);
}
public List<VixHostConfig> getHosts() {
if (hosts == null) {
hosts = new ArrayList<VixHostConfig>();
// provide default if we have none
hosts.add(new VixHostConfig());
}
return hosts;
}
public void setHosts(List<VixHostConfig> hosts) {
this.hosts = hosts;
}
public VixHostConfig getHost(String name) {
for (VixHostConfig host : hosts) {
if (name.equals(host.getName())) {
return host;
}
}
return null;
}
public String[] getHostNames() {
String[] result = new String[hosts.size()];
for (int i = 0; i < result.length; i++) {
result[i] = hosts.get(i).getName();
}
return result;
}
public void addHost(VixHostConfig hostConfig) {
hosts.add(hostConfig);
save();
}
public VMWrapperPowerUpMode[] getPowerUpModes() {
return VMWrapperPowerUpMode.values();
}
public VMWrapperPowerDownMode[] getPowerDownModes() {
return VMWrapperPowerDownMode.values();
}
}
public static final class VMActivationConfig implements Serializable {
private final VMWrapperPowerUpMode powerUpMode;
private final VMWrapperPowerDownMode powerDownMode;
private final int waitTimeout;
private final boolean waitForFeedback;
private final String feedbackKey;
private final int feedbackTimeout;
private final VixVirtualComputerConfig config;
@Override
public String toString() {
return config.toPseudoUri();
}
@DataBoundConstructor
public VMActivationConfig(VMWrapperPowerUpMode powerUpMode, VMWrapperPowerDownMode powerDownMode,
int waitTimeout,
boolean waitForFeedback, String feedbackKey, int feedbackTimeout,
VixVirtualComputerConfig config) {
this.powerUpMode = powerUpMode;
this.powerDownMode = powerDownMode;
this.waitTimeout = waitTimeout;
this.waitForFeedback = waitForFeedback;
this.feedbackKey = feedbackKey;
this.feedbackTimeout = feedbackTimeout;
this.config = config;
}
public int getWaitTimeout() {
return waitTimeout <= 0 ? 300 : waitTimeout;
}
public VMWrapperPowerUpMode getPowerUpMode() {
return powerUpMode;
}
public VMWrapperPowerDownMode getPowerDownMode() {
return powerDownMode;
}
public String getPreBuild() {
return powerUpMode == null ? null : powerUpMode.toString();
}
public String getPostBuild() {
return powerDownMode == null ? null : powerDownMode.toString();
}
public boolean isWaitForFeedback() {
return waitForFeedback && feedbackKey != null && feedbackKey.trim().length() > 0;
}
public String getFeedbackKey() {
return feedbackKey;
}
public int getFeedbackTimeout() {
return feedbackTimeout < 0 ? 300 : feedbackTimeout;
}
public VixVirtualComputerConfig getConfig() {
return config;
}
}
private static final Logger LOGGER = Logger.getLogger(VMwareActivationWrapper.class.getName());
}