Using Java to create customized virtual machine clones on VMWare infrastructure

陆沈浪
2023-12-01
Hello. Quite a while ago I was given a task to create a java module which would be able to create customized clones from existing virtual machines, managed by vSphere. Main focus was on creating clones, which has unique network settings so all machines can be used for testing at once on same network. To do this, I utilized an open source java library called VIJAVA , which is a Java API to VMWare infrastructure. It offers you pretty big set of operations, which you can do on top of the VMWare infrastructure. In this post I will focus only on cloning task with customized specification.

Generally the procedure to create customized clone is following:

Connect to vSphere
Load a machine we will use as a template
Create a customization specification, which is a configuration of a clone
Create a clone with customization
Power it ON


Code Example

Now let’s show some examples. Before we start, you will need access to vSphere and have access with privileges to create/modify/delete machines on infrastructure. Also i recommend to see http://vijava.sourceforge.net/doc/getstarted/tutorial.htm for a vijava setup. Or if you are using maven, you can add following dependency into your pom file

<dependency>
<groupId>com.vmware</groupId>
<artifactId>vijava</artifactId>
<version>5.1</version>
</dependency>

Now let’s see the actual example code, that connects to vSphere, load the template machines, creates clone specifications and clones the machine. Code should be pretty self explaining with inline comments.

import com.vmware.vim25.*;
import com.vmware.vim25.mo.*;
 
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
 
/**
 * Sample code for creating customized Linux/Windows VM clone from template using VIJAVA
 */
public class VMManager {
    public static void main(String args[]) throws MalformedURLException,
            RemoteException, InterruptedException {
        //Define needed vars
        String vSphereUrl = "https://vsphere.example.com:1234/sdk";
        String vSpherePassword = "password";
        String vSphereUsername  = "username";
 
        String templateVMName = "template-machine1";
        String cloneName = "vm-1";
 
        //Connect to vSphere server using VIJAVA
        ServiceInstance si = new ServiceInstance(new URL(vSphereUrl),vSphereUsername,vSpherePassword);
 
        //Find the template machine in the inventory
        InventoryNavigator inventoryNavigator = new InventoryNavigator(si.getRootFolder());
        VirtualMachine vmTemplate = (VirtualMachine) inventoryNavigator.
                searchManagedEntity("VirtualMachine", templateVMName);
 
        //Create customization for cloning process(Uncomment the one you need)
        VirtualMachineCloneSpec cloneSpec = createLinuxCustomization();
        //VirtualMachineCloneSpec cloneSpec = createWindowsCustomization();
        //Do the cloning - providing the clone specification
        Task cloneTask = vmTemplate.cloneVM_Task((Folder) vmTemplate.getParent(),cloneName,cloneSpec);
        cloneTask.waitForTask();
 
        //Here is our new customized virtual machine ready
        VirtualMachine vm = (VirtualMachine) inventoryNavigator.searchManagedEntity("VirtualMachine", cloneName);
        vm.powerOnVM_Task(null).waitForTask();
    }
 
    public static VirtualMachineCloneSpec createLinuxCustomization(){
        VirtualMachineCloneSpec vmCloneSpec = new VirtualMachineCloneSpec();
 
        //Set location of clone to be the same as template (Datastore)
        vmCloneSpec.setLocation(new VirtualMachineRelocateSpec());
 
        //Clone is not powered on, not a template.
        vmCloneSpec.setPowerOn(false);
        vmCloneSpec.setTemplate(false);
 
        //Create customization specs/linux specific options
        CustomizationSpec customSpec = new CustomizationSpec();
        CustomizationLinuxOptions linuxOptions = new CustomizationLinuxOptions();
        customSpec.setOptions(linuxOptions);
 
        CustomizationLinuxPrep linuxPrep = new CustomizationLinuxPrep();
        linuxPrep.setDomain("example.domain.com");
        linuxPrep.setHwClockUTC(true);
        linuxPrep.setTimeZone("Europe/London");
 
        CustomizationFixedName fixedName = new CustomizationFixedName();
        fixedName.setName("cloned-machine-hostname");
        linuxPrep.setHostName(fixedName);
        customSpec.setIdentity(linuxPrep);
 
        //Network related settings
        CustomizationGlobalIPSettings globalIPSettings = new CustomizationGlobalIPSettings();
        globalIPSettings.setDnsServerList(new String[]{"8.8.8.8", "8.8.4.4"});
        globalIPSettings.setDnsSuffixList(new String[]{"search.com","my.search.com"});
        customSpec.setGlobalIPSettings(globalIPSettings);
 
        CustomizationFixedIp fixedIp = new CustomizationFixedIp();
        fixedIp.setIpAddress("192.168.10.1");
 
        CustomizationIPSettings customizationIPSettings = new CustomizationIPSettings();
        customizationIPSettings.setIp(fixedIp);
        customizationIPSettings.setGateway(new String[]{"192.168.1.1"});
        customizationIPSettings.setSubnetMask("255.255.0.0");
 
        CustomizationAdapterMapping adapterMapping = new CustomizationAdapterMapping();
        adapterMapping.setAdapter(customizationIPSettings);
 
        CustomizationAdapterMapping[] adapterMappings = new CustomizationAdapterMapping[]{adapterMapping};
        customSpec.setNicSettingMap(adapterMappings);
 
        //Set all customization to clone specs
        vmCloneSpec.setCustomization(customSpec);
        return vmCloneSpec;
    }
 
    public static VirtualMachineCloneSpec createWindowsCustomization(){
        //Windows needs valid product key in order to create fully working clone. Otherwise you will get error message
        //when machine is cloned
        String productID="XXXXX-XXXXX-XXXXXX-XXXXX";
 
        VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
 
        //Set location of clone to be the same as template (Datastore)
        cloneSpec.setLocation(new VirtualMachineRelocateSpec());
 
        //Clone is not powered on, not a template.
        cloneSpec.setPowerOn(false);
        cloneSpec.setTemplate(false);
 
        //Create customization specs/win specific options
        //Windows are using SYSPREP for these kind of stuff
        CustomizationSpec customSpec = new CustomizationSpec();
        CustomizationWinOptions winOptions = new CustomizationWinOptions();
 
        winOptions.setChangeSID(true);
        //We don't want our preconfigured users to be deleted
        winOptions.setDeleteAccounts(false);
 
        customSpec.setOptions(winOptions);
        CustomizationSysprep sprep = new CustomizationSysprep();
 
        CustomizationGuiUnattended guiUnattended = new CustomizationGuiUnattended();
        guiUnattended.setAutoLogon(false);
        guiUnattended.setAutoLogonCount(0);
        guiUnattended.setTimeZone(4);
        sprep.setGuiUnattended(guiUnattended);
 
        CustomizationIdentification custIdent = new CustomizationIdentification();
        custIdent.setJoinWorkgroup("WORKGROUP");
        sprep.setIdentification(custIdent);
 
        CustomizationUserData custUserData = new CustomizationUserData();
        CustomizationFixedName fixedName = new CustomizationFixedName();
        fixedName.setName("windows-clone");
 
        //set from cloned machine
        custUserData.setProductId(productID);     // REQUIRED FOR Windows
        custUserData.setComputerName(fixedName);
        custUserData.setFullName("windows-clone.example.com");
        custUserData.setOrgName("example.com");
 
        sprep.setUserData(custUserData);
        customSpec.setIdentity(sprep);
 
        //Network related settings
        CustomizationGlobalIPSettings globalIPSettings = new CustomizationGlobalIPSettings();
        globalIPSettings.setDnsServerList(new String[]{"8.8.8.8","8.8.4.4"});
        globalIPSettings.setDnsSuffixList(new String[]{"example.com"});
 
        customSpec.setGlobalIPSettings(globalIPSettings);
        CustomizationFixedIp fixedIp = new CustomizationFixedIp();
        fixedIp.setIpAddress("192.168.10.2");
 
        CustomizationIPSettings customizationIPSettings = new CustomizationIPSettings();
        customizationIPSettings.setIp(fixedIp);
        customizationIPSettings.setGateway(new String[]{"192.168.1.1"});
        customizationIPSettings.setSubnetMask("255.255.0.0");
 
        //Disabling netBIOS
        customizationIPSettings.setNetBIOS(CustomizationNetBIOSMode.disableNetBIOS);
        customizationIPSettings.setDnsDomain("example.com");
 
        CustomizationAdapterMapping adapterMapping = new CustomizationAdapterMapping();
        adapterMapping.setAdapter(customizationIPSettings);
 
        CustomizationAdapterMapping[] adapterMappings = new CustomizationAdapterMapping[]{adapterMapping};
        customSpec.setNicSettingMap(adapterMappings);
 
        //Set all customization to clone specs
        cloneSpec.setCustomization(customSpec);
 
        return cloneSpec;
    }
}

Note that all customization properties what you can see in the method above are required otherwise you will get exception related to bad XML parsing. From my experience, process of cloning Linux machine is flawless and i never experienced any kind of problems except when i missed customization properties. On a infrastructure I was working, this process took around 3 minutes to fully booted and prepared machine(CentOS 6.4 Linux OS). Looks like windows is more time consuming with this operation as it took around 5 minutes. Also it’s good to mention, that for a successful cloning of Windows VM, you will need a valid product key for Windows.

 类似资料:

相关阅读

相关文章

相关问答