package hudson.plugins.virtualization; import hudson.Extension; import hudson.Functions; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.model.Descriptor; import hudson.model.Hudson; import hudson.model.Resource; import hudson.model.ResourceActivity; import hudson.model.ResourceList; import hudson.slaves.Cloud; import hudson.slaves.ComputerLauncher; import hudson.tasks.BuildWrapper; import net.java.dev.vcc.api.Computer; import net.java.dev.vcc.api.Datacenter; import net.java.dev.vcc.api.PowerState; import net.java.dev.vcc.api.commands.StartComputer; import net.java.dev.vcc.api.commands.SuspendComputer; import net.sf.json.JSONObject; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.StaplerRequest; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * A virtual computer that is used as a build resource. */ public class VirtualComputerBuildWrapper extends BuildWrapper implements ResourceActivity { private final List<VirtualComputerResource> resources; @DataBoundConstructor public VirtualComputerBuildWrapper(VirtualComputerResource[] resources) throws Descriptor.FormException, IOException { this.resources = Collections.unmodifiableList(new ArrayList<VirtualComputerResource>(Arrays.asList(resources))); } public VirtualComputerResource[] getResources() { return resources.toArray(new VirtualComputerResource[resources.size()]); } @Override public Environment setUp(AbstractBuild abstractBuild, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { class EnvironmentImpl extends Environment { @Override public boolean tearDown(AbstractBuild abstractBuild, BuildListener listener) throws IOException, InterruptedException { boolean failed = false; for (VirtualComputerResource resource : resources) { VirtualComputer virtualComputer = resource.getVirtualComputer(); if (virtualComputer == null) { continue; } String name = virtualComputer.getName(); Datacenter datacenter = virtualComputer.getDatacenter().getConnection(); for (Computer c : datacenter.getAllComputers()) { if (virtualComputer.getName().equals(c.getName())) { listener.getLogger() .println("[virtualization] Virtual computer " + name + " is in state " + c .getState()); if (PowerState.RUNNING.equals(c.getState())) { listener.getLogger() .println("[virtualization] Suspending virtual computer " + name); try { SuspendComputer future = c.execute(new SuspendComputer()); while (!PowerState.SUSPENDED.equals(c.getState())) { try { future.get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { listener.getLogger().println( "[virtualization] Waiting for virtual computer " + name + " to suspend..."); } } listener.getLogger() .println("[virtualization] Virtual computer " + name + " suspended"); } catch (ExecutionException e) { listener .error("[virtualization] Could not suspend virtual computer {0}", name); e.printStackTrace(listener.getLogger()); failed = true; } } else { listener.getLogger() .println("[virtualization] Virtual computer " + name + " is already suspended"); } } } } return !failed; } } boolean failed = false; for (VirtualComputerResource resource : resources) { VirtualComputer virtualComputer = resource.getVirtualComputer(); if (virtualComputer == null) { continue; } Datacenter datacenter = virtualComputer.getDatacenter().getConnection(); boolean found = false; String name = virtualComputer.getName(); for (Computer c : datacenter.getAllComputers()) { if (name.equals(c.getName())) { found = true; listener.getLogger() .println("[virtualization] Virtual computer " + name + " is in state " + c.getState()); if (!PowerState.RUNNING.equals(c.getState())) { listener.getLogger().println("[virtualization] Starting virtual computer " + name); try { StartComputer future = c.execute(new StartComputer()); while (!PowerState.RUNNING.equals(c.getState())) { try { future.get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { listener.getLogger().println( "[virtualization] Waiting for virtual computer " + name + " to start..."); } } listener.getLogger().println("[virtualization] Virtual computer " + name + " started"); } catch (ExecutionException e) { listener.fatalError("[virtualization] Could not start virtual computer {0}", name); e.printStackTrace(listener.getLogger()); failed = true; } } else { listener.getLogger() .println("[virtualization] Virtual computer " + name + " is already started"); } break; } } if (!found) { failed = true; listener.getLogger().println("[virtualization] Could not find virtual computer " + name); break; } } if (failed) { new EnvironmentImpl().tearDown(abstractBuild, listener); return null; } return new EnvironmentImpl(); } public ResourceList getResourceList() { ResourceList result = new ResourceList(); for (VirtualComputerResource r : resources) { result.w(r.getResource()); } return result; } public String getDisplayName() { return getDescriptor().getDisplayName(); } private static VirtualComputer findVirtualComputer(String datacenterUri, String computerName) { computerName.getClass(); for (VirtualComputer c : ((DescriptorImpl) Hudson.getInstance() .getDescriptor(VirtualComputerBuildWrapper.class)) .getVirtualComputers()) { if ((datacenterUri == null || datacenterUri.equals(c.getDatacenterUri())) && computerName .equals(c.getComputerName())) { return c; } } return null; } public static final class VirtualComputerResource implements Serializable { private final String datacenterUri; private final String computerName; private transient VirtualComputer virtualComputer = null; private transient Resource resource = null; @DataBoundConstructor public VirtualComputerResource(String datacenterUri, String computerName) throws IOException { datacenterUri.getClass(); // throw NPE if null computerName.getClass(); // throw NPE if null this.datacenterUri = datacenterUri; this.computerName = computerName; } public String getDatacenterUri() { return datacenterUri; } public String getComputerName() { return computerName; } public synchronized VirtualComputer getVirtualComputer() { if (virtualComputer == null) { virtualComputer = findVirtualComputer(datacenterUri, computerName); } return virtualComputer; } public synchronized Resource getResource() { if (resource == null) { resource = new Resource(new Resource(null, datacenterUri), computerName); } return resource; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } VirtualComputerResource that = (VirtualComputerResource) o; if (!computerName.equals(that.computerName)) { return false; } if (!datacenterUri.equals(that.datacenterUri)) { return false; } return true; } @Override public int hashCode() { int result = datacenterUri.hashCode(); result = 31 * result + computerName.hashCode(); return result; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("VirtualComputerResource"); sb.append("{datacenterUri='").append(datacenterUri).append('\''); sb.append(", computerName='").append(computerName).append('\''); sb.append('}'); return sb.toString(); } } @Extension public static final class DescriptorImpl extends Descriptor<BuildWrapper> { public DescriptorImpl() { super(VirtualComputerBuildWrapper.class); } public String getDisplayName() { return "Use a virtual computer running on a virtualization platform (via vcc-api) as a build resource"; } public Set<VirtualComputer> getVirtualComputers() { SortedSet<VirtualComputer> result = new TreeSet<VirtualComputer>(); for (Cloud cloud : Hudson.getInstance().clouds) { if (cloud instanceof VirtualDatacenter) { VirtualDatacenter datacenter = VirtualDatacenter.class.cast(cloud); result.addAll(datacenter.getVirtualComputers().values()); } } return result; } public List<VirtualDatacenter> getDatacenters() { List<VirtualDatacenter> result = new ArrayList<VirtualDatacenter>(); for (Cloud cloud : Hudson.getInstance().clouds) { if (cloud instanceof VirtualDatacenter) { result.add((VirtualDatacenter) cloud); } } return result; } public List<Descriptor<ComputerLauncher>> getComputerLauncherDescriptors() { List<Descriptor<ComputerLauncher>> result = new ArrayList<Descriptor<ComputerLauncher>>(); for (Descriptor<ComputerLauncher> launcher : Functions.getComputerLauncherDescriptors()) { if (!VirtualComputerLauncher.DESCRIPTOR.getClass().isAssignableFrom(launcher.getClass())) { result.add(launcher); } } return result; } @Override public BuildWrapper newInstance(StaplerRequest staplerRequest, JSONObject jsonObject) throws FormException { System.out.println(jsonObject); return super.newInstance(staplerRequest, jsonObject); //To change body of overridden methods use File | Settings | File Templates. } } }