1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.redhat.vmtruckloader.vmware.action;
24
25 import java.rmi.RemoteException;
26
27 import org.redhat.vmtruckloader.service.MachineSpecification;
28 import org.redhat.vmtruckloader.vmware.VMWareMachineSpecsUtils;
29 import org.redhat.vmtruckloader.vmware.VMWareManagedObjectUtils;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import com.vmware.vim25.VirtualDevice;
34 import com.vmware.vim25.VirtualDeviceConfigSpec;
35 import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
36 import com.vmware.vim25.VirtualEthernetCard;
37 import com.vmware.vim25.VirtualMachineCloneSpec;
38 import com.vmware.vim25.VirtualMachineRelocateSpec;
39 import com.vmware.vim25.mo.Datastore;
40 import com.vmware.vim25.mo.Folder;
41 import com.vmware.vim25.mo.ResourcePool;
42 import com.vmware.vim25.mo.ServiceInstance;
43 import com.vmware.vim25.mo.Task;
44 import com.vmware.vim25.mo.VirtualMachine;
45
46
47
48
49
50
51
52
53 public class CloneMachineCallback extends AbstractVMWareActionCallback<MachineSpecification> {
54
55 private static final Logger LOGGER = LoggerFactory.getLogger(CloneMachineCallback.class);
56 private final String sourceMachineName;
57 private MachineSpecification spec;
58
59 public CloneMachineCallback(final String sourceMachineName, MachineSpecification machineSpecification) {
60 this.sourceMachineName = sourceMachineName;
61 this.spec = machineSpecification;
62 }
63
64 private VirtualMachineRelocateSpec buildRelocateSpec(ServiceInstance serviceInstance) {
65 VirtualMachineRelocateSpec relocateSpec = new VirtualMachineRelocateSpec();
66
67 final String mssg = "Can't retrieve ResourcePool named " + spec.getResourcePoolName();
68 ResourcePool pool = VMWareManagedObjectUtils.findResourcePoolByName(serviceInstance, spec.getResourcePoolName());
69 if ( pool == null ) {
70 LOGGER.error(mssg);
71 throw new IllegalArgumentException(mssg);
72 }
73 relocateSpec.pool = pool.getMOR();
74
75 Datastore store = VMWareManagedObjectUtils.findDataStore(spec.getDatastoreName(), spec.getDiskSize(), serviceInstance);
76 relocateSpec.datastore = store.getMOR();
77
78 return relocateSpec;
79 }
80
81 private void specDebugInfo(VirtualMachineCloneSpec cloneSpec, VirtualMachine sourceVm) {
82 if ( LOGGER.isDebugEnabled() ) {
83 LOGGER.debug("- sourceVm.getParent():" + sourceVm.getParent());
84 LOGGER.debug("- name:" + spec.getHostname() );
85 LOGGER.debug("- cloneSpec:" + cloneSpec.toString() );
86 }
87 }
88
89 private void retrieveAndRemoveExistingEthernetCard(VirtualMachine sourceVm,VirtualMachineCloneSpec cloneSpec ) {
90 if ( sourceVm == null )
91 throw new IllegalArgumentException("SourceVM is 'null', can't clone VM");
92 for ( VirtualDevice device : sourceVm.getConfig().getHardware().getDevice() ) {
93 if ( LOGGER.isDebugEnabled() )
94 LOGGER.debug("Device found:" + device.getDeviceInfo().getLabel() + "[" + device.getClass() + "]");
95 if ( device instanceof VirtualEthernetCard ) {
96 VirtualEthernetCard nic = (VirtualEthernetCard) device;
97 VirtualDeviceConfigSpec nicSpec = new VirtualDeviceConfigSpec();
98 nicSpec.setDevice(nic);
99 nicSpec.setOperation(VirtualDeviceConfigSpecOperation.remove);
100 cloneSpec.getConfig().deviceChange[1] = nicSpec;
101 }
102 }
103 }
104
105 @Override
106 public MachineSpecification doInVmware(ServiceInstance serviceInstance) {
107 VirtualMachineRelocateSpec relocateSpec = buildRelocateSpec(serviceInstance);
108
109 VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
110 cloneSpec.template = false;
111 cloneSpec.powerOn = false;
112 cloneSpec.location = relocateSpec;
113 cloneSpec.setConfig(VMWareMachineSpecsUtils.buildVmSpec(serviceInstance, this.spec));
114
115 VirtualMachine sourceVm = VMWareManagedObjectUtils.getVm(serviceInstance, sourceMachineName);
116 retrieveAndRemoveExistingEthernetCard(sourceVm, cloneSpec);
117 Task task;
118 try {
119 specDebugInfo(cloneSpec, sourceVm);
120 Folder setupFolder = VMWareManagedObjectUtils.lookVmFolder(serviceInstance, spec.getFolder());
121
122 task = sourceVm.cloneVM_Task(setupFolder, spec.getHostname(), cloneSpec);
123 LOGGER.debug("TaskKey = " + task.getTaskInfo().key);
124
125 try {
126 String status = task.waitForTask();
127 if ( ! Task.SUCCESS.equals(status))
128 throw new IllegalStateException("Operation fails (status:" + status + ") - resulting clone, if any, may not be in a consistent state." +
129 "Also checks if there is not already a VM called " + spec.getHostname());
130 } catch (InterruptedException ie) {
131 LOGGER.error("Interrupted while waiting for cloning of machine '" + sourceMachineName + "' to '"
132 + spec.getHostname() + "' in resource pool '" + spec.getHostname() + "'.", ie);
133 Thread.currentThread().interrupt();
134 }
135 return new VirtualMachineTransformer(spec).getMacAddress(VMWareManagedObjectUtils.getVm(serviceInstance, spec.getVmName()));
136 } catch (RemoteException re) {
137 String errorMessage = "Error while cloning '" + sourceMachineName + "' to '" + spec.getHostname() + "' in resource pool '"
138 + spec.getResourcePoolName() + "'.";
139 LOGGER.error(errorMessage, re);
140 throw new IllegalArgumentException(errorMessage, re);
141 }
142 }
143 }