/** * Copyright (C) 2010, Byte-Code srl <http://www.byte-code.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Date: Mar 04, 2010 * Author: Marco Mornati<mmornati@byte-code.com> */ package hudson.plugins.libvirt; import hudson.slaves.ComputerLauncher; import hudson.slaves.SlaveComputer; import hudson.model.TaskListener; import hudson.model.Descriptor; import hudson.model.Hudson; import hudson.Extension; import hudson.slaves.Cloud; import java.io.IOException; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.kohsuke.stapler.DataBoundConstructor; import org.libvirt.Domain; import org.libvirt.DomainInfo.DomainState; public class VirtualMachineLauncher extends ComputerLauncher { private static final Logger LOGGER = Logger.getLogger(VirtualMachineLauncher.class.getName()); private ComputerLauncher delegate; private transient VirtualMachine virtualMachine; private String hypervisorDescription; private String virtualMachineName; private static final int WAIT_TIME = 60000; @DataBoundConstructor public VirtualMachineLauncher(ComputerLauncher delegate, String hypervisorDescription, String virtualMachineName) { super(); this.delegate = delegate; this.virtualMachineName = virtualMachineName; this.hypervisorDescription = hypervisorDescription; buildVirtualMachine(); } private void buildVirtualMachine() { if (hypervisorDescription != null && virtualMachineName != null) { LOGGER.log(Level.INFO, "Building virtual machine object from names"); Hypervisor hypervisor = null; for (Cloud cloud : Hudson.getInstance().clouds) { if (cloud instanceof Hypervisor && ((Hypervisor) cloud).getHypervisorDescription().equals(hypervisorDescription)) { hypervisor = (Hypervisor) cloud; break; } } LOGGER.log(Level.INFO, "Hypervisor found... getting Virtual Machines associated"); for (VirtualMachine vm : hypervisor.getVirtualMachines()) { if (vm.getName().equals(virtualMachineName)) { virtualMachine = vm; break; } } } } public ComputerLauncher getDelegate() { return delegate; } public VirtualMachine getVirtualMachine() { return virtualMachine; } @Override public boolean isLaunchSupported() { return delegate.isLaunchSupported(); } @Override public void launch(SlaveComputer slaveComputer, TaskListener taskListener) throws IOException, InterruptedException { taskListener.getLogger().println("Getting connection to the virtual datacenter"); if (virtualMachine == null) { taskListener.getLogger().println("No connection ready to the Hypervisor... reconnecting..."); buildVirtualMachine(); } try { Map<String, Domain> computers = virtualMachine.getHypervisor().getDomains(); taskListener.getLogger().println("Looking for the virtual machine on Hypervisor..."); for (String domainName : computers.keySet()) { if (virtualMachine.getName().equals(domainName)) { taskListener.getLogger().println("Virtual Machine Found"); Domain domain = computers.get(domainName); if (domain.getInfo().state != DomainState.VIR_DOMAIN_BLOCKED && domain.getInfo().state != DomainState.VIR_DOMAIN_RUNNING) { taskListener.getLogger().println("Starting virtual machine"); domain.create(); taskListener.getLogger().println("Waiting " + WAIT_TIME + "ms for machine startup"); Thread.sleep(WAIT_TIME); } else { taskListener.getLogger().println("Virtual machine is already running. No startup procedure required."); } taskListener.getLogger().println("Finished startup procedure... Connecting slave client"); delegate.launch(slaveComputer, taskListener); return; } } taskListener.getLogger().println("Error! Could not find virtual machine on the hypervisor"); throw new IOException("VM not found!"); } catch (IOException e) { e.printStackTrace(taskListener.getLogger()); throw e; } catch (Throwable t) { t.printStackTrace(taskListener.getLogger()); } } @Override public void afterDisconnect(SlaveComputer slaveComputer, TaskListener taskListener) { taskListener.getLogger().println("Running disconnect procedure..."); delegate.afterDisconnect(slaveComputer, taskListener); taskListener.getLogger().println("Shutting down Virtual Machine..."); try { Map<String, Domain> computers = virtualMachine.getHypervisor().getDomains(); taskListener.getLogger().println("Looking for the virtual machine on Hypervisor..."); for (String domainName : computers.keySet()) { if (virtualMachine.getName().equals(domainName)) { Domain domain = computers.get(domainName); taskListener.getLogger().println("Virtual Machine Found"); if (domain.getInfo().state.equals(DomainState.VIR_DOMAIN_RUNNING) || domain.getInfo().state.equals(DomainState.VIR_DOMAIN_BLOCKED)) { taskListener.getLogger().println("Shutting down virtual machine"); domain.shutdown(); } else { taskListener.getLogger().println("Virtual machine is already suspended. No shutdown procedure required."); } return; } } taskListener.getLogger().println("Error! Could not find virtual machine on the hypervisor"); } catch (Throwable t) { taskListener.fatalError(t.getMessage(), t); } } @Override public void beforeDisconnect(SlaveComputer slaveComputer, TaskListener taskListener) { delegate.beforeDisconnect(slaveComputer, taskListener); } @Override public Descriptor<ComputerLauncher> getDescriptor() { return Hudson.getInstance().getDescriptor(getClass()); } @Extension public static final Descriptor<ComputerLauncher> DESCRIPTOR = new Descriptor<ComputerLauncher>() { private String hypervisorDescription; private String virtualMachineName; private ComputerLauncher delegate; public String getDisplayName() { return "Virtual Machine Launcher"; } public String getHypervisorDescription() { return hypervisorDescription; } public String getVirtualMachineName() { return virtualMachineName; } public ComputerLauncher getDelegate() { return delegate; } }; }