/******************************************************************************* * Copyright 2012 Urbancode, Inc * * 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 com.urbancode.terraform.tasks.vmware; import java.rmi.RemoteException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import com.urbancode.terraform.tasks.vmware.events.CloneVmCreatedEvent; import com.urbancode.terraform.tasks.vmware.events.TaskEventListener; import com.urbancode.terraform.tasks.vmware.events.TaskEventService; import com.urbancode.terraform.tasks.vmware.util.GlobalIpAddressPool; import com.urbancode.terraform.tasks.vmware.util.Ip4; import com.urbancode.terraform.tasks.vmware.util.IpInUseException; import com.urbancode.terraform.tasks.vmware.util.Path; import com.urbancode.terraform.tasks.vmware.util.VirtualHost; import com.urbancode.x2o.tasks.Restorable; import com.vmware.vim25.GuestInfo; import com.vmware.vim25.GuestNicInfo; import com.vmware.vim25.InvalidProperty; import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.NotFound; import com.vmware.vim25.RuntimeFault; import com.vmware.vim25.VimFault; import com.vmware.vim25.VirtualMachineCloneSpec; import com.vmware.vim25.VirtualMachinePowerState; import com.vmware.vim25.VirtualMachineRelocateDiskMoveOptions; import com.vmware.vim25.VirtualMachineRelocateSpec; import com.vmware.vim25.VirtualMachineRuntimeInfo; import com.vmware.vim25.VirtualMachineSnapshotInfo; import com.vmware.vim25.VirtualMachineSnapshotTree; import com.vmware.vim25.VirtualMachineToolsStatus; import com.vmware.vim25.mo.ComputeResource; import com.vmware.vim25.mo.Datacenter; import com.vmware.vim25.mo.Datastore; import com.vmware.vim25.mo.Folder; import com.vmware.vim25.mo.HostSystem; import com.vmware.vim25.mo.ManagedEntity; import com.vmware.vim25.mo.ResourcePool; import com.vmware.vim25.mo.Task; import com.vmware.vim25.mo.VirtualMachine; public class CloneTask extends com.urbancode.x2o.tasks.SubTask implements Restorable, Cloneable, Comparable<CloneTask> { // ********************************************************************************************** // CLASS // ********************************************************************************************** static private final Logger log = Logger.getLogger(CloneTask.class); // ********************************************************************************************** // INSTANCE // ********************************************************************************************** private String instanceName; private String snapshotName = ""; private int count = 1; private int order = 1; // default to front of queue private VirtualMachine vm; private Path imagePath; private boolean poweredOn = false; private boolean assignHostIp = false; private boolean assignPrivateIpOnly = false; private boolean sentPowerDown = false; private String publicIp = ""; private String privateIp = ""; private EnvironmentTaskVmware environment; private List<Ip4> ipList = new ArrayList<Ip4>(); private List<NetworkRefTask> networkRefs = new ArrayList<NetworkRefTask>(); private List<SecurityGroupRefTask> securityGroupRefs = new ArrayList<SecurityGroupRefTask>(); private List<TaskEventListener> listeners = new ArrayList<TaskEventListener>(); private List<PostCreateTask> postCreateTaskList = new ArrayList<PostCreateTask>(); private String user; private String password; //---------------------------------------------------------------------------------------------- public CloneTask() { super(); } //---------------------------------------------------------------------------------------------- public CloneTask(EnvironmentTaskVmware environment) { super(); this.environment = environment; } //---------------------------------------------------------------------------------------------- public EnvironmentTaskVmware fetchEnvironment() { return this.environment; } //---------------------------------------------------------------------------------------------- public VirtualMachine fetchVm() { return this.vm; } //---------------------------------------------------------------------------------------------- public String getUser() { return user; } //---------------------------------------------------------------------------------------------- public String getPassword() { return "${" + instanceName + ".password}"; } //---------------------------------------------------------------------------------------------- public String fetchPassword() { return password; } //---------------------------------------------------------------------------------------------- public Path getImagePath() { return this.imagePath; } //---------------------------------------------------------------------------------------------- public String getSnapshotName() { return this.snapshotName; } //---------------------------------------------------------------------------------------------- public boolean getPoweredOn() { return this.poweredOn; } //---------------------------------------------------------------------------------------------- public String getInstanceName() { return this.instanceName; } //---------------------------------------------------------------------------------------------- public boolean getAssignHostIp() { return this.assignHostIp; } //---------------------------------------------------------------------------------------------- public boolean getAssignPrivateIpOnly() { return this.assignPrivateIpOnly; } //---------------------------------------------------------------------------------------------- public String getPublicIp() { return publicIp; } //---------------------------------------------------------------------------------------------- public String getPrivateIp() { return privateIp; } //---------------------------------------------------------------------------------------------- public int getOrder() { return this.order; } //---------------------------------------------------------------------------------------------- public String getIpList() { String result; StringBuilder builder = new StringBuilder(); boolean first = true; for (Ip4 ip : ipList) { if (first) { builder.append(ip.toString()); first = false; } else { builder.append("," + ip.toString()); } } result = builder.toString(); return result; } //---------------------------------------------------------------------------------------------- public List<NetworkRefTask> getNetworkRefs() { return this.networkRefs; } //---------------------------------------------------------------------------------------------- public List<SecurityGroupRefTask> getSecurityGroupRefs() { return this.securityGroupRefs; } //---------------------------------------------------------------------------------------------- public List<PostCreateTask> getPostCreateTaskList() { return this.postCreateTaskList; } //---------------------------------------------------------------------------------------------- public List<TaskEventListener> getEventListeners() { return this.listeners; } //---------------------------------------------------------------------------------------------- public void setUser(String user) { this.user = user; } //---------------------------------------------------------------------------------------------- public void setPassword(String password) { this.password = password; } //---------------------------------------------------------------------------------------------- public void setInstanceName(String instanceName) { this.instanceName = instanceName; } //---------------------------------------------------------------------------------------------- public void setSnapshotName(String snapshotName) { this.snapshotName = snapshotName; } //---------------------------------------------------------------------------------------------- public void setImagePath(String imagePathString) { Path imagePth = new Path(imagePathString); this.imagePath = imagePth; } //---------------------------------------------------------------------------------------------- public void setPoweredOn(boolean poweredOn) { this.poweredOn = poweredOn; } //---------------------------------------------------------------------------------------------- public void setAssignHostIp(boolean assignHostIp) { this.assignHostIp = assignHostIp; } //---------------------------------------------------------------------------------------------- public void setAssignPrivateIpOnly(boolean assignPrivateIpOnly) { this.assignPrivateIpOnly = assignPrivateIpOnly; } //---------------------------------------------------------------------------------------------- public void setPublicIp(String publicIp) { this.publicIp = publicIp; } //---------------------------------------------------------------------------------------------- public void setPrivateIp(String privateIp) { this.privateIp = privateIp; } //---------------------------------------------------------------------------------------------- public void setOrder(int order) { this.order = order; } //---------------------------------------------------------------------------------------------- /** * Sets the IP stored IP list and allocates the IPs in the Global IP Pool. * @param ipListAsString comma separated list of IP addresses */ public void setIpList(String ipListAsString) { ipList.clear(); String[] split = ipListAsString.split(","); for (int i=0; i<split.length; i++) { Ip4 ip = new Ip4(split[i]); ipList.add(ip); //ensure IPs are reserved GlobalIpAddressPool globalIpPool = GlobalIpAddressPool.getInstance(); try { globalIpPool.reserveIp(ip); } catch(IpInUseException e) { log.error("Ip " + ip + " already in use!"); } } } //---------------------------------------------------------------------------------------------- /** * Retrieves IP addresses on the VM from vCenter. The VI Java API's method for returning * the IP addresses can be unreliable - it depends on when the VM is polled by Terraform. * Only IPv4 addresses will be added - IPv6 addresses are ignored right now. * Sets the IP addresses as a comma-separated list. This will be written out to XML. */ public void setIpListFromVmInfo() { ipList.clear(); GuestNicInfo[] nicInfos = vm.getGuest().getNet(); if (nicInfos == null) { log.warn("problem retrieving network info from VM"); } else { for (int i=0; i<nicInfos.length; i++) { String[] nicInfoIpList = nicInfos[i].getIpAddress(); for (int j=0; j<nicInfoIpList.length; j++) { //ip4 addresses only; vsphere 5 likes to return ip4 and ip6 String unparsedIp = nicInfoIpList[j]; if (!unparsedIp.contains(":")) { Ip4 newIp = new Ip4(unparsedIp); ipList.add(newIp); } } } } } //---------------------------------------------------------------------------------------------- public void setCount(int count) { this.count = count; } //---------------------------------------------------------------------------------------------- public void setEnvironment(EnvironmentTaskVmware environment) { this.environment = environment; } //---------------------------------------------------------------------------------------------- public TaskEventListener addEventListener(TaskEventListener listener) { this.listeners.add(listener); listener.setValues(this); return listener; } //---------------------------------------------------------------------------------------------- public PostCreateTask addPostCreateTask(PostCreateTask task) { task.setValues(this); this.postCreateTaskList.add(task); return task; } //---------------------------------------------------------------------------------------------- public PostCreateTask addCommand(PostCreateTask task) { task.setValues(this); this.postCreateTaskList.add(task); return task; } //---------------------------------------------------------------------------------------------- public PostCreateTask addCopyFile(PostCreateTask task) { task.setValues(this); this.postCreateTaskList.add(task); return task; } //---------------------------------------------------------------------------------------------- public NetworkRefTask createNetworkRef() { NetworkRefTask result = new NetworkRefTask(); this.networkRefs.add(result); return result; } //---------------------------------------------------------------------------------------------- public SecurityGroupRefTask createSecurityGroupRef() { SecurityGroupRefTask result = new SecurityGroupRefTask(); this.securityGroupRefs.add(result); return result; } //---------------------------------------------------------------------------------------------- public void runPostCreateTasks() { for (PostCreateTask task : postCreateTaskList) { task.setUser(user); task.setPassword(password); task.create(); } } //---------------------------------------------------------------------------------------------- /** * Clones from a template if no snapshot is specified, or from a linked clone if a valid * snapshot is specified. * @return * @throws RemoteException * @throws InterruptedException */ public VirtualMachine cloneVM() throws RemoteException, InterruptedException { VirtualMachine result = null; VirtualHost host = environment.fetchVirtualHost(); Path hostPath = environment.getHostPath(); Path storePath = environment.getDatastorePath(); Folder destFolder = environment.fetchFolderTask().getFolder(); boolean isTemplate = !(snapshotName.length() > 0); VirtualMachine template = null; template = fetchOriginalVm(imagePath, isTemplate); ComputeResource computeResource = host.getComputeResource(hostPath); ResourcePool pool = computeResource.getResourcePool(); VirtualMachineRelocateSpec location = new VirtualMachineRelocateSpec(); location.setPool(pool.getMOR()); if (storePath != null) { location.setDatastore(fetchDatastore(storePath).getMOR()); } VirtualMachineCloneSpec spec = new VirtualMachineCloneSpec(); spec.setLocation(location); spec.setPowerOn(poweredOn); if (!isTemplate) { log.info("creating vm " + instanceName + " from snapshot " + snapshotName); ManagedObjectReference snapshotMOR = fetchSnapshotRef(template, snapshotName); spec.setSnapshot(snapshotMOR); location.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.createNewChildDiskBacking .toString()); } Task task = template.cloneVM_Task(destFolder, instanceName, spec); @SuppressWarnings("unused") String status = task.waitForTask(); Object taskResult = task.getTaskInfo().getResult(); if (taskResult instanceof VirtualMachine) { result = (VirtualMachine) taskResult; } else if (taskResult instanceof ManagedObjectReference) { result = new VirtualMachine(host.getServiceInstance() .getServerConnection(), (ManagedObjectReference) taskResult); } return result; } //---------------------------------------------------------------------------------------------- /** * Searches the snapshot tree for the specified snapshot. * @param snapTree * @param snapshotName * @return */ private ManagedObjectReference traverseSnapshotInTree( VirtualMachineSnapshotTree[] snapTree, String snapshotName) { ManagedObjectReference result = null; if (snapTree != null && snapshotName != null) { for (int i = 0; i < snapTree.length && result == null; i++) { VirtualMachineSnapshotTree node = snapTree[i]; if (node.getName().equals(snapshotName)) { result = node.getSnapshot(); } else { VirtualMachineSnapshotTree[] childTree = snapTree[i] .getChildSnapshotList(); result = traverseSnapshotInTree(childTree, snapshotName); } } } return result; } //---------------------------------------------------------------------------------------------- public int fetchCount() { return this.count; } //---------------------------------------------------------------------------------------------- private ManagedObjectReference fetchSnapshotRef(VirtualMachine vm, String snapshotName) { ManagedObjectReference result = null; VirtualMachineSnapshotInfo snapInfo = vm.getSnapshot(); if (snapInfo != null) { VirtualMachineSnapshotTree[] snapTree = snapInfo .getRootSnapshotList(); result = traverseSnapshotInTree(snapTree, snapshotName); } return result; } //---------------------------------------------------------------------------------------------- public Datastore fetchDatastore(Path path) throws RemoteException { Datastore result = null; VirtualHost host = environment.fetchVirtualHost(); Datacenter datacenter = host.getDatacenterFromEnd(environment.fetchDatacenterPath()); for (Datastore d : datacenter.getDatastores()) { if (d.getName().equals(path.getName())) { result = d; break; } } if (result == null) { throw new NotFound(); } return result; } //---------------------------------------------------------------------------------------------- public VirtualMachine fetchOriginalVm(Path path, boolean isTemplate) throws RemoteException { VirtualMachine result = null; Folder folder = fetchFolder(path.getParent()); String targetName = path.getName(); // find template for (ManagedEntity e : folder.getChildEntity()) { if (e instanceof VirtualMachine && e.getName().equals(targetName)) { VirtualMachine vmTemplate = (VirtualMachine) e; if (vmTemplate.getConfig().isTemplate() == isTemplate) { result = vmTemplate; break; } } } if (result == null) { throw new NotFound(); } return result; } //---------------------------------------------------------------------------------------------- public VirtualMachine fetchVmForPath(Path path) throws RemoteException { VirtualMachine result = null; Folder folder = fetchFolder(path.getParent()); String targetName = path.getName(); log.debug("looking for vm " + targetName + " in folder " + path.getParent().toString()); // find template for (ManagedEntity e : folder.getChildEntity()) { if (e instanceof VirtualMachine && e.getName().equals(targetName)) { VirtualMachine vmTemplate = (VirtualMachine) e; result = vmTemplate; break; } } if (result == null) { throw new NotFound(); } return result; } //---------------------------------------------------------------------------------------------- public Folder fetchFolder(Path path) throws RemoteException { Folder result = null; VirtualHost host = environment.fetchVirtualHost(); //fixed to accomodate datacenters on root folder, need to check if works for nonroot case List<String> folderNames = path.toList(); Path datacenterPath = environment.fetchDatacenterPath(); //on restoration and destruction if (datacenterPath == null) { // traverse folders result = host.getRootFolder(); Folder nextFolder = null; for (String fName : folderNames) { for (ManagedEntity e : result.getChildEntity()) { log.trace("Searching ManagedEntity " + e.getName() + " for fname " + fName); if (e instanceof Folder && e.getName().equals(fName)) { nextFolder = (Folder) e; break; } else if (e instanceof Datacenter && e.getName().equals(fName)) { Datacenter datacenter = (Datacenter) e; nextFolder = datacenter.getVmFolder(); break; } } if (nextFolder == null) { throw new NotFound(); } result = nextFolder; nextFolder = null; } if (result == null) { throw new NotFound(); } } //on creation else{ Datacenter datacenter = host.getDatacenterFromEnd(datacenterPath); List<String> skippableFolders = datacenterPath.toList(); // traverse folders result = datacenter.getVmFolder(); Folder nextFolder = null; for (String fName : folderNames) { if (!skippableFolders.contains(fName)){ for (ManagedEntity e : result.getChildEntity()) { log.trace("Searching ManagedEntity " + e.getName() + " for fname " + fName); if (e instanceof Folder && e.getName().equals(fName)) { nextFolder = (Folder) e; break; } } if (nextFolder == null) { throw new NotFound(); } result = nextFolder; nextFolder = null; } } if (result == null) { throw new NotFound(); } } return result; } //---------------------------------------------------------------------------------------------- /** * Generates a status for a VM based on whether it is powered on and has VMTools running. * @return A string representing the VM status. */ public String fetchVmStatus() { String result = null; try { if (vm == null) { if (sentPowerDown) { result = "Shut Down"; } else { result = "Starting"; } } else { GuestInfo guestInfo = vm.getGuest(); VirtualMachineToolsStatus vmToolsStatus = guestInfo.getToolsStatus(); VirtualMachineRuntimeInfo vmri = vm.getRuntime(); VirtualMachinePowerState powerStatus = vmri.getPowerState(); if (vmToolsStatus.equals(VirtualMachineToolsStatus.toolsOk) && powerStatus.equals(VirtualMachinePowerState.poweredOn)) { if (sentPowerDown) { result = "Shutting Down"; } else { result = "Running"; } } else if (vmToolsStatus.equals(VirtualMachineToolsStatus.toolsOld) || vmToolsStatus.equals(VirtualMachineToolsStatus.toolsNotInstalled)) { if (powerStatus.equals(VirtualMachinePowerState.poweredOn)) { if (sentPowerDown) { result = "Shutting Down"; } else { result = "Powered On"; } } else if (powerStatus.equals(VirtualMachinePowerState.poweredOff)) { if (sentPowerDown) { result = "Shutting Down"; } else { result = "Powered Off Or Starting"; } } } else if (vmToolsStatus.equals(VirtualMachineToolsStatus.toolsNotRunning)) { if (powerStatus.equals(VirtualMachinePowerState.poweredOn)) { result = "Starting"; } else if (powerStatus.equals(VirtualMachinePowerState.poweredOff)) { result = "Not Started or Powered Off"; } } } } catch(Exception e) { if (sentPowerDown) { result = "Shut Down"; } else { log.warn("An exception was reached while retrieving VM status. Status set to Unknown.", e); result = "Unknown"; } } if (result == null) { result = "Unknown"; } return result; } //---------------------------------------------------------------------------------------------- /** * Powers off the VM stored in this CloneTask object. This is a "hard" powering off. * @throws InvalidProperty * @throws RuntimeFault * @throws RemoteException * @throws InterruptedException */ public void powerOffVm() throws InvalidProperty, RuntimeFault, RemoteException, InterruptedException { VirtualMachineRuntimeInfo vmri = vm.getRuntime(); if (vmri.getPowerState() == VirtualMachinePowerState.poweredOn) { sentPowerDown = true; com.vmware.vim25.mo.Task task = vm.powerOffVM_Task(); task.waitForTask(); log.info("vm:" + vm.getName() + " powered off."); } } //---------------------------------------------------------------------------------------------- public void powerOnVm() throws InvalidProperty, RuntimeFault, RemoteException, InterruptedException { Path hostPath = this.environment.getHostPath(); VirtualHost host = this.environment.fetchVirtualHost(); ComputeResource res = host.getComputeResource(hostPath); HostSystem hostSystem = res.getHosts()[0]; VirtualMachineRuntimeInfo vmri = vm.getRuntime(); if (vmri.getPowerState() == VirtualMachinePowerState.poweredOff || vmri.getPowerState() == VirtualMachinePowerState.suspended) { com.vmware.vim25.mo.Task task = vm.powerOnVM_Task(hostSystem); task.waitForTask(); log.info("vm:" + vm.getName() + " powered on."); } } //---------------------------------------------------------------------------------------------- /** * Attempts to suspend the VM stored in this CloneTask object according to its OS's suspend command. * @throws InvalidProperty * @throws RuntimeFault * @throws RemoteException * @throws InterruptedException */ public void suspendVm() throws InvalidProperty, RuntimeFault, RemoteException, InterruptedException { VirtualMachineRuntimeInfo vmri = vm.getRuntime(); if (vmri.getPowerState() == VirtualMachinePowerState.poweredOn) { com.vmware.vim25.mo.Task task = vm.suspendVM_Task(); task.waitForTask(); log.info("vm:" + vm.getName() + " was suspended."); } } //---------------------------------------------------------------------------------------------- /** * Takes a snapshot of this VM. THe name of the snapshot is the current date and time. * The format of the name is yyyy-mm-dd hh:mm:ss * @throws VimFault * @throws RemoteException * @throws InterruptedException */ public void takeSnapshotOfVm() throws VimFault, RemoteException, InterruptedException { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); String name = dateFormat.format(date); String description = "created by Terraform's take-snapshot command"; Task task = vm.createSnapshot_Task(name, description, false, false); if (task.waitForTask() == Task.SUCCESS) { log.info("Created snapshot with name : " + name + " on virtual machine " + instanceName); } } //---------------------------------------------------------------------------------------------- /** * Restores the Virtual Machine object for the vm field for this object. * @throws RemoteException */ public void restoreVm() throws RemoteException { // restore by vm name and folder Path folderPath = environment.fetchFolderTask().getFolderRef(); Path vmPath = new Path(folderPath, instanceName); this.vm = fetchOriginalVm(vmPath, false); } //---------------------------------------------------------------------------------------------- /** * Attempts to delete the VM from disk. * @throws RemoteException * @throws InterruptedException */ public void removeVm() throws RemoteException, InterruptedException { try { Task task = vm.destroy_Task(); String status = task.waitForTask(); if (!status.equals("success")) { String message = task.getTaskInfo().getError() .getLocalizedMessage(); throw new RemoteException("Failed: " + message); } } catch (NotFound e) { log.warn("VM not found before attempting to delete it", e); } } //---------------------------------------------------------------------------------------------- /** * This is an override of the Java clone() method and has nothing to do with cloning VMs. */ @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } //---------------------------------------------------------------------------------------------- /** * Compares 2 CloneTasks based on their order attribute. Clones are executed from * lowest to highest. If order is equal they are executed in parallel. */ @Override public int compareTo(CloneTask o) { int result; int other = o.getOrder(); //if order is not specified, default is max_int (back of the queue) //lowest order number is highest priority if (this.order < other) { result = -1; } else if (this.order == other) { result = 0; } else { result = 1; } return result; } //---------------------------------------------------------------------------------------------- /** * Creates the VM clone by cloning the specified image. * This is currently done from a template if no snapshot is specified, or done via a * linked clone if a snapshot is specified. Linked clones are much faster. * After the VM is cloned, NICs will be attached, routing rules will be applied (if a router * exists), post create tasks will be run, and then the VM will be powered on. Note that * post create tasks may power on the VM first anyways. */ @Override public void create() { log.debug("Calling create method on clone"); TaskEventService eventService = environment.fetchEventService(); for (TaskEventListener listener : listeners) { eventService.addEventListener(listener); } try { this.vm = cloneVM(); for (NetworkRefTask networkRef : networkRefs) { networkRef.setVirtualSwitch(environment.restoreNetworkForName(networkRef.getNetworkName()).fetchSwitch()); networkRef.setVirtualMachine(this.vm); networkRef.setVirtualHost(environment.fetchVirtualHost()); networkRef.create(); } for (SecurityGroupRefTask sgr : securityGroupRefs) { sgr.setSecurityGroup(environment.restoreSecurityGroupForName(sgr.getName())); } } catch (RemoteException e) { log.warn("remote exception when creating clone task", e); } catch (InterruptedException e) { log.warn("interrupted exception when creating clone task", e); } catch (Exception e) { log.warn("unknown exception when creating clone task", e); } CloneVmCreatedEvent actionEvent = new CloneVmCreatedEvent(this); environment.fetchEventService().sendEvent(actionEvent); runPostCreateTasks(); try { powerOnVm(); } catch (Exception e) { log.warn("exception when powering on vm", e); } } //---------------------------------------------------------------------------------------------- /** * Deletes the VM from disc and frees any IP addresses that were allocated to it. */ @Override public void destroy() { try { restoreVm(); try { for(PostCreateTask pct : postCreateTaskList) { pct.destroy(); } } catch (Exception e) { log.warn("exception while destroying post create tasks", e); } GlobalIpAddressPool globalIpPool = GlobalIpAddressPool.getInstance(); for (Ip4 ip : ipList) { globalIpPool.releaseIp(ip); } powerOffVm(); removeVm(); } catch (RemoteException e) { log.warn("remote exception when deleting clone task", e); } catch (InterruptedException e) { log.warn("interruption exception when deleting clone task", e); } } //---------------------------------------------------------------------------------------------- /** * Restores the VM and network reference fields for this CloneTask. */ @Override public void restore() { try { restoreVm(); GlobalIpAddressPool globalIpPool = GlobalIpAddressPool.getInstance(); for (NetworkRefTask networkRef : networkRefs) { networkRef.setVirtualSwitch(environment.restoreNetworkForName(networkRef.getNetworkName()).fetchSwitch()); networkRef.setVirtualMachine(this.vm); networkRef.setVirtualHost(environment.fetchVirtualHost()); } } catch (RemoteException e) { log.warn("remote exception when restoring clone task", e); } } }