This section shows how to create a VirtualMachine object, which is complicated but necessary so you can restore data into it. Before creating this object, you must create a VirtualMachineConfigSpec describing the virtual machine and all of its supporting virtual devices. Almost all the required information is available from the virtual machine property config.hardware.device, which is a table containing the device configuration information. The relationships between devices are described by the value key, which is a unique identifier for the device. In turn, each device has a controllerKey, which is the key identifier of the controller where the device is connected. Use negative integers as temporary key values in the VirtualMachineConfigSpec to guarantee that temporary key numbers do not conflict with real key numbers when they are assigned by the server. When associating virtual devices with default devices, the controllerKey property should be reset with the key property of the controller. Below are the settings for a sample VirtualMachineConfigSpec used to create a virtual machine.

// beginning of VirtualMachineConfigSpec, ends several pages later
{
   dynamicType = <unset>,
   changeVersion = <unset>,
//This is the display name of the VM
   name = “My New VM“,
   version = "vmx-04",
   uuid = <unset>,
   instanceUuid = <unset>,
   npivWorldWideNameType = <unset>,
   npivDesiredNodeWwns = <unset>,
   npivDesiredPortWwns = <unset>,
   npivTemporaryDisabled = <unset>,
   npivOnNonRdmDisks = <unset>,
   npivWorldWideNameOp = <unset>,
   locationId = <unset>,
// This is advisory, the disk determines the O/S
guestId = "winNetStandardGuest",
   alternateGuestName = "Microsoft Windows Server 2008, Enterprise Edition",
   annotation = <unset>,
   files = (vim.vm.FileInfo) {
      dynamicType = <unset>,
      vmPathName = "[plat004-local]",
      snapshotDirectory = "[plat004-local]",
      suspendDirectory = <unset>,
      logDirectory = <unset>,
   },
   tools = (vim.vm.ToolsConfigInfo) {
      dynamicType = <unset>,
      toolsVersion = <unset>,
      afterPowerOn = true,
      afterResume = true,
      beforeGuestStandby = true,
      beforeGuestShutdown = true,
      beforeGuestReboot = true,
      toolsUpgradePolicy = <unset>,
      pendingCustomization = <unset>,
      syncTimeWithHost = <unset>,
   },
   flags = (vim.vm.FlagInfo) {
      dynamicType = <unset>,
      disableAcceleration = <unset>,
      enableLogging = <unset>,
      useToe = <unset>,
      runWithDebugInfo = <unset>,
      monitorType = <unset>,
      htSharing = <unset>,
      snapshotDisabled = <unset>,
      snapshotLocked = <unset>,
      diskUuidEnabled = <unset>,
      virtualMmuUsage = <unset>,
      snapshotPowerOffBehavior = "powerOff",
      recordReplayEnabled = <unset>,
   },
   consolePreferences = (vim.vm.ConsolePreferences) null,
   powerOpInfo = (vim.vm.DefaultPowerOpInfo) {
      dynamicType = <unset>,
      powerOffType = "preset",
      suspendType = "preset",
      resetType = "preset",
      defaultPowerOffType = <unset>,
      defaultSuspendType = <unset>,
      defaultResetType = <unset>,
      standbyAction = "powerOnSuspend",
   },
   // the number of CPUs
   numCPUs = 1,
   // the number of memory megabytes
   memoryMB = 256,
   memoryHotAddEnabled = <unset>,
   cpuHotAddEnabled = <unset>,
   cpuHotRemoveEnabled = <unset>,
   deviceChange = (vim.vm.device.VirtualDeviceSpec) [
      (vim.vm.device.VirtualDeviceSpec) {
         dynamicType = <unset>,
         operation = "add",
         fileOperation = <unset>,
         // CDROM
         device = (vim.vm.device.VirtualCdrom) {
            dynamicType = <unset>,
            // key number of CDROM
            key = -42,
            deviceInfo = (vim.Description) null,
            backing = (vim.vm.device.VirtualCdrom.RemotePassthroughBackingInfo) {
               dynamicType = <unset>,
               deviceName = "",
               useAutoDetect = <unset>,
               exclusive = false,
            },
            connectable = (vim.vm.device.VirtualDevice.ConnectInfo) {
               dynamicType = <unset>,
               startConnected = false,
               allowGuestControl = true,
               connected = false,
            },
            // connects to this controller
            controllerKey = 200,
            unitNumber = 0,
         },
      },
      (vim.vm.device.VirtualDeviceSpec) {
         dynamicType = <unset>,
         operation = "add",
         fileOperation = <unset>,
         // SCSI controller
         device = (vim.vm.device.VirtualLsiLogicController) {
            dynamicType = <unset>,
// key number of SCSI controller
            key = -44,
            deviceInfo = (vim.Description) null,
            backing = (vim.vm.device.VirtualDevice.BackingInfo) null,
            connectable = (vim.vm.device.VirtualDevice.ConnectInfo) null,
            controllerKey = <unset>,
            unitNumber = <unset>,
            busNumber = 0,
            hotAddRemove = <unset>,
            sharedBus = "noSharing",
            scsiCtlrUnitNumber = <unset>,
         },
      },
      (vim.vm.device.VirtualDeviceSpec) {
         dynamicType = <unset>,
         operation = "add",
         fileOperation = <unset>,
         // Network controller
         device = (vim.vm.device.VirtualPCNet32) {
            dynamicType = <unset>,
            // key number of Network controller
            key = -48,
            deviceInfo = (vim.Description) null,
            backing = (vim.vm.device.VirtualEthernetCard.NetworkBackingInfo) {
               dynamicType = <unset>,
               deviceName = "Virtual Machine Network",
               useAutoDetect = <unset>,
               network = <unset>,
               inPassthroughMode = <unset>,
            },
            connectable = (vim.vm.device.VirtualDevice.ConnectInfo) {
               dynamicType = <unset>,
               startConnected = true,
               allowGuestControl = true,
               connected = true,
            },
            controllerKey = <unset>,
            unitNumber = <unset>,
            addressType = "generated",
            macAddress = <unset>,
            wakeOnLanEnabled = true,
         },
      },
      (vim.vm.device.VirtualDeviceSpec) {
         dynamicType = <unset>,
         operation = "add",
         fileOperation = "create",
         // SCSI disk one
         device = (vim.vm.device.VirtualDisk) {
            dynamicType = <unset>,
            // key number for SCSI disk one
            key = -1000000,
            deviceInfo = (vim.Description) null,
            backing = (vim.vm.device.VirtualDisk.FlatVer2BackingInfo) {
               dynamicType = <unset>,
               fileName = "",
               datastore = <unset>,
               diskMode = "persistent",
               split = false,
               writeThrough = false,
               thinProvisioned = <unset>,
               eagerlyScrub = <unset>,
               uuid = <unset>,
               contentId = <unset>,
               changeId = <unset>,
               parent = (vim.vm.device.VirtualDisk.FlatVer2BackingInfo) null,
            },
            connectable = (vim.vm.device.VirtualDevice.ConnectInfo) {
               dynamicType = <unset>,
               startConnected = true,
               allowGuestControl = false,
               connected = true,
            },
            // controller for SCSI disk one
            controllerKey = -44,
            unitNumber = 0,
            // size in MB SCSI disk one
            capacityInKB = 524288,
            committedSpace = <unset>,
            shares = (vim.SharesInfo) null,
         },
      },
      (vim.vm.device.VirtualDeviceSpec) {
         dynamicType = <unset>,
         operation = "add",
         fileOperation = "create",
         // SCSI disk two
         device = (vim.vm.device.VirtualDisk) {
            dynamicType = <unset>,
// key number of SCSI disk two
            key = -100,
            deviceInfo = (vim.Description) null,
            backing = (vim.vm.device.VirtualDisk.FlatVer2BackingInfo) {
               dynamicType = <unset>,
               fileName = "",
               datastore = <unset>,
               diskMode = "persistent",
               split = false,
               writeThrough = false,
               thinProvisioned = <unset>,
               eagerlyScrub = <unset>,
               uuid = <unset>,
               contentId = <unset>,
               changeId = <unset>,
               parent = (vim.vm.device.VirtualDisk.FlatVer2BackingInfo) null,
            },
            connectable = (vim.vm.device.VirtualDevice.ConnectInfo) {
               dynamicType = <unset>,
               startConnected = true,
               allowGuestControl = false,
               connected = true,
            },
            // controller for SCSI disk two
            controllerKey = -44,
            unitNumber = 1,
            // size in MB SCSI disk two
            capacityInKB = 131072,
            committedSpace = <unset>,
            shares = (vim.SharesInfo) null,
         },
      }
   },
   cpuAllocation = (vim.ResourceAllocationInfo) {
      dynamicType = <unset>,
      reservation = 0,
      expandableReservation = <unset>,
      limit = <unset>,
      shares = (vim.SharesInfo) {
         dynamicType = <unset>,
         shares = 100,
         level = "normal",
      },
      overheadLimit = <unset>,
   },
   memoryAllocation = (vim.ResourceAllocationInfo) {
      dynamicType = <unset>,
      reservation = 0,
      expandableReservation = <unset>,
      limit = <unset>,
      shares = (vim.SharesInfo) {
         dynamicType = <unset>,
         shares = 100,
         level = "normal",
      },
      overheadLimit = <unset>,
   },
   cpuAffinity = (vim.vm.AffinityInfo) null,
   memoryAffinity = (vim.vm.AffinityInfo) null,
   networkShaper = (vim.vm.NetworkShaperInfo) null,
   swapPlacement = <unset>,
   swapDirectory = <unset>,
   preserveSwapOnPowerOff = <unset>,
   bootOptions = (vim.vm.BootOptions) null,
   appliance = (vim.vService.ConfigSpec) null,
   ftInfo = (vim.vm.FaultToleranceConfigInfo) null,
   applianceConfigRemoved = <unset>,
   vAssertsEnabled = <unset>,
   changeTrackingEnabled = <unset>,
}
// end of VirtualMachineConfigSpec

The information above is quite complex, but much of the input consists of defaulted values that are assigned by the system. The remainder of the supplied information can be extracted from the output of the config.hardware.device table returned from PropertyCollector. Borrowing heavily from an SDK code example, the following code sets up the configuration specification:

// Duplicate virtual machine configuration
VirtualMachineConfigSpec configSpec = new VirtualMachineConfigSpec();
// Set the VM values
configSpec.setName("My New VM");
configSpec.setVersion("vmx-04");
configSpec.setGuestId("winNetStandardGuest");
configSpec.setNumCPUs(1);
configSpec.setMemoryMB(256);
// Set up file storage info
VirtualMachineFileInfo vmfi = new VirtualMachineFileInfo();
vmfi.setVmPathName("[plat004-local]");
configSpec.setFiles(vmfi);
vmfi.setSnapshotDirectory("[plat004-local]");
// Set up tools config info
ToolsConfigInfo tools = new ToolsConfigInfo();
configSpec.setTools(tools);
tools.setAfterPowerOn(new Boolean(true));
tools.setAfterResume(new Boolean(true));
tools.setBeforeGuestStandby(new Boolean(true));
tools.setBeforeGuestShutdown(new Boolean(true));
tools.setBeforeGuestReboot(new Boolean(true));
// Set flags
VirtualMachineFlagInfo flags = new VirtualMachineFlagInfo();
configSpec.setFlags(flags);
flags.setSnapshotPowerOffBehavior("powerOff");
// Set power op info
VirtualMachineDefaultPowerOpInfo powerInfo = new VirtualMachineDefaultPowerOpInfo();
configSpec.setPowerOpInfo(powerInfo);
powerInfo.setPowerOffType("preset");
powerInfo.setSuspendType("preset");
powerInfo.setResetType("preset");
powerInfo.setStandbyAction("powerOnSuspend");
// Now add in the devices
VirtualDeviceConfigSpec[] deviceConfigSpec = new VirtualDeviceConfigSpec [5];
configSpec.setDeviceChange(deviceConfigSpec);
// Formulate the CDROM
deviceConfigSpec[0].setOperation(VirtualDeviceConfigSpecOperation.add);
VirtualCdrom cdrom = new VirtualCdrom();
VirtualCdromIsoBackingInfo cdDeviceBacking = new  VirtualCdromRemotePassthroughBackingInfo();
cdDeviceBacking.setDatastore(datastoreRef);
cdrom.setBacking(cdDeviceBacking);
cdrom.setKey(-42);
cdrom.setControllerKey(new Integer(-200)); // Older Java required type for optional properties
cdrom.setUnitNumber(new Integer(0));
deviceConfigSpec[0].setDevice(cdrom);
// Formulate the SCSI controller
deviceConfigSpec[1].setOperation(VirtualDeviceConfigSpecOperation.add);
VirtualLsiLogicController scsiCtrl = new VirtualLsiLogicController();
scsiCtrl.setBusNumber(0);
deviceConfigSpec[1].setDevice(scsiCtrl);
scsiCtrl.setKey(-44);
scsiCtrl.setSharedBus(VirtualSCSISharing.noSharing);
// Formulate SCSI disk one
deviceConfigSpec[2].setFileOperation(VirtualDeviceConfigSpecFileOperation.create);
deviceConfigSpec[2].setOperation(VirtualDeviceConfigSpecOperation.add);
VirtualDisk disk =  new VirtualDisk();
VirtualDiskFlatVer2BackingInfo diskfileBacking = new VirtualDiskFlatVer2BackingInfo();
diskfileBacking.setDatastore(datastoreRef);
diskfileBacking.setFileName(volumeName);
diskfileBacking.setDiskMode("persistent");
diskfileBacking.setSplit(new Boolean(false));
diskfileBacking.setWriteThrough(new Boolean(false));
disk.setKey(-1000000);
disk.setControllerKey(new Integer(-44));
disk.setUnitNumber(new Integer(0));
disk.setBacking(diskfileBacking);
disk.setCapacityInKB(524288);
deviceConfigSpec[2].setDevice(disk);
// Formulate SCSI disk two
deviceConfigSpec[3].setFileOperation(VirtualDeviceConfigSpecFileOperation.create);
deviceConfigSpec[3].setOperation(VirtualDeviceConfigSpecOperation.add);
VirtualDisk disk2 =  new VirtualDisk();
VirtualDiskFlatVer2BackingInfo diskfileBacking2 = new VirtualDiskFlatVer2BackingInfo();
diskfileBacking2.setDatastore(datastoreRef);
diskfileBacking2.setFileName(volumeName);
diskfileBacking2.setDiskMode("persistent");
diskfileBacking2.setSplit(new Boolean(false));
diskfileBacking2.setWriteThrough(new Boolean(false));
disk2.setKey(-100);
disk2.setControllerKey(new Integer(-44));
disk2.setUnitNumber(new Integer(1));
disk2.setBacking(diskfileBacking2);
disk2.setCapacityInKB(131072);
deviceConfigSpec[3].setDevice(disk2);
// Finally, formulate the NIC
deviceConfigSpec[4].setOperation(VirtualDeviceConfigSpecOperation.add);
com.VMware.vim.VirtualEthernetCard nic =  new VirtualPCNet32();
VirtualEthernetCardNetworkBackingInfo nicBacking = new VirtualEthernetCardNetworkBackingInfo();
nicBacking.setNetwork(networkRef);
nicBacking.setDeviceName(networkName);
nic.setAddressType("generated");
nic.setBacking(nicBacking);
nic.setKey(-48);
deviceConfigSpec[4].setDevice(nic);
// Now that it is all put together, create the virtual machine.
// Note that folderMo, resourcePool, and hostMo, are moRefs to
// the Folder, ResourcePool, and Host where the VM is to be created.
ManagedObjectReference taskMoRef =
    serviceConnection.getService().createVM_Task(folderMo, configSpec, resourcePool, hostMo);