In our environment, we need to be able to quickly deploy out multiple clones of a template as quick as possible without regard to their performance. This is how we have it working in the code:
1) Mark template as VM
2) Grab the VM's hardware, look for any VirtualDisk devices, keep track of the devices, and remove them from the VM using ReconfigVM_Task
3) Mark as template
4) for (i = 1 to n)
1) Clone VM while adding all VMDK files we keep track of before as existing disks
2) Take a snapshot before powering it on
5) Convert original template to VM
6) Reconfigure adding the drives back in
7) Convert back to template
So, the running VMs run off of disk deltas. We did some quick tests and didn't notice a performance difference (we're not running servers here, just test machines)
You can do this using the VI client and it works great. Even when you delete the cloned VM it only deletes the deltas, not the original drive.
But we can't seem to get this to work in the code. The problem is adding the existing VMDK to the VirtualMachineCloneSpec.
Here's the code were we try and add the VMDK files back:
// Add disks back
removedDisksConfigSpecs = new List();
foreach (VirtualDisk device in removedDisks)
VirtualDeviceConfigSpec diskSpec = new VirtualDeviceConfigSpec();
diskSpec.operation = VirtualDeviceConfigSpecOperation.add;
diskSpec.operationSpecified = true;
VirtualDisk disk = new VirtualDisk();
VirtualDiskFlatVer2BackingInfo diskFileBacking = new VirtualDiskFlatVer2BackingInfo();
diskFileBacking.datastore = (device.backing as VirtualDiskFlatVer2BackingInfo).datastore;
diskFileBacking.fileName = (device.backing as VirtualDiskFlatVer2BackingInfo).fileName;
diskFileBacking.diskMode = "persistent";
disk.key = 0;
disk.controllerKey = device.controllerKey;
disk.unitNumber = device.unitNumber;
disk.backing = diskFileBacking;
disk.capacityInKB = device.capacityInKB;
disk.controllerKeySpecified = true;
disk.unitNumberSpecified = true;
diskSpec.device = disk;
vmCloneSpec.config.deviceChange = removedDisksConfigSpecs.ToArray();
The clone operation is successful, but when you look at the actual settings the added disk's file backing (as seen in the VI client's Edit Settings dialog):
The file is very small, and has:
RW 2048 VMFSSPARSE "oldvmname-000001-delta.vmdk"
The Disk Data Base
It actually works pretty well, but when you delete the cloned VM, it deletes the parentFileNameHint (the original VMDK), whereas doing it manually in VI client does not. In fact, in the VI client, the file backing for the "Add Existing Disk" option shows the path to the original VMDK, not this -0000001.vmdk stuff.
Does anyone know how to really add an existing VMDK file? Or, is it possible to see the SOAP messages the VI client is sending? I could perhaps figure it out from there.
What version of VC are you using?
To monitor the SOAP message, you got to change the HTTPS to HTTP. I think there are descriptions in the installation guide of VI SDK or the programming guide.
Looks like I was mistaken. The oldvmname-000001.vmdk is simply the result of the snapshot operation. Also, strangely enough, both the manual method and the code method delete the original disk when you destroy the VM (which makes sense). Maybe, when we did the tests manually, we removed from inventory rather than actually destroying.
To fix this issue, we "destroy" a VM by removing it from the inventory and then deleting it's folder from the Datastore. A two step process that recovers the disk space and leaves the original disk intact.
Oh, and if anyone is following down this path as well, you don't need to manually create a new VirtualDisk device and transfer over the settings. If you have a reference to the disk you removed, you can simply add it as a deviceChange with the operation being add. It works very nicey and can be done in a single line of code