in cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/vmware/connector/VMWareApiConnectorImpl.java [782:890]
public Task cloneAndStartVm(@NotNull final VmwareCloudInstance instance) throws VmwareCheckedCloudException {
final VmwareCloudImageDetails imageDetails = instance.getImage().getImageDetails();
LOG.info(String.format("Attempting to clone VM %s into %s", imageDetails.getSourceVmName(), instance.getName()));
final Pair<VirtualMachine, Datacenter> pair = findEntityByIdNameOld(imageDetails.getSourceVmName(), VirtualMachine.class);
final VirtualMachine vm = pair.getFirst();
final Datacenter datacenter = pair.getSecond();
final VirtualMachineConfigSpec config = new VirtualMachineConfigSpec();
final VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
final VirtualMachineRelocateSpec location = new VirtualMachineRelocateSpec();
cloneSpec.setPowerOn(true);
cloneSpec.setLocation(location);
cloneSpec.setConfig(config);
final boolean disableOsCustomization = TeamCityProperties.getBoolean(VmwareConstants.DISABLE_OS_CUSTOMIZATION);
if (!VmwareConstants.DEFAULT_RESOURCE_POOL.equals(imageDetails.getResourcePoolId())) {
final ResourcePool pool = findEntityByIdNameNullableOld(imageDetails.getResourcePoolId(), ResourcePool.class, datacenter);
if (pool != null) {
location.setPool(pool.getMOR());
} else {
LOG.warn(String.format("Unable to find resource pool %s at datacenter %s. Will clone at the image resource pool instead"
, imageDetails.getResourcePoolId()
, datacenter == null? "<not provided>": datacenter.getName()));
}
}
final Map<String, VirtualMachineSnapshotTree> snapshotList = getSnapshotList(vm);
final VmwareSourceState sourceState = instance.getSourceState();
if (imageDetails.useCurrentVersion() || StringUtil.isEmptyOrSpaces(sourceState.getSnapshotName())) {
LOG.info("Snapshot name is not specified. Will clone latest VM state");
} else {
final VirtualMachineSnapshotTree obj = snapshotList.get(sourceState.getSnapshotName());
final ManagedObjectReference snapshot = obj == null ? null : obj.getSnapshot();
cloneSpec.setSnapshot(snapshot);
if (snapshot != null) {
if (TeamCityProperties.getBooleanOrTrue(VmwareConstants.USE_LINKED_CLONE)) {
LOG.info("Using linked clone. Snapshot name: " + sourceState.getSnapshotName());
location.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.createNewChildDiskBacking.name());
} else {
LOG.info("Using full clone. Snapshot name: " + sourceState.getSnapshotName());
}
} else {
final String errorText = "Unable to find snapshot " + sourceState.getSnapshotName();
throw new VmwareCheckedCloudException(errorText);
}
}
final VirtualMachineConfigInfo vmConfig = vm.getConfig();
config.setExtraConfig(new OptionValue[]{
createOptionValue(TEAMCITY_VMWARE_CLONED_INSTANCE, "true"),
createOptionValue(TEAMCITY_VMWARE_IMAGE_SOURCE_VM_NAME, imageDetails.getSourceVmName()),
createOptionValue(TEAMCITY_VMWARE_IMAGE_SOURCE_ID, imageDetails.getSourceId()),
createOptionValue(TEAMCITY_VMWARE_IMAGE_SOURCE_VM_ID, vm.getMOR().getVal()),
createOptionValue(TEAMCITY_VMWARE_IMAGE_SNAPSHOT, sourceState.getSnapshotName()),
createOptionValue(TEAMCITY_VMWARE_IMAGE_CHANGE_VERSION, vmConfig.getChangeVersion()),
createOptionValue(TEAMCITY_VMWARE_PROFILE_ID, StringUtil.emptyIfNull(myProfileId)),
createOptionValue(TEAMCITY_VMWARE_SERVER_UUID, StringUtil.emptyIfNull(myServerUUID))
});
final GuestInfo guest = vm.getGuest();
String guestFamily = guest != null ? guest.getGuestFamily() : null;
if (guestFamily == null){
final String guestFullName = vmConfig.getGuestFullName();
if (guestFullName != null && guestFullName.contains("Linux")){
guestFamily = LINUX_GUEST_FAMILY;
}
}
if (StringUtil.isNotEmpty(imageDetails.getCustomizationSpec())){
LOG.info(String.format("Will use Customization Spec '%s' to clone %s into %s"
, imageDetails.getCustomizationSpec(), imageDetails.getSourceVmName(), instance.getName()));
cloneSpec.setCustomization(getCustomizationSpec(imageDetails.getCustomizationSpec()));
} else if (!disableOsCustomization && myDomain != null && LINUX_GUEST_FAMILY.equals(guestFamily)){
LOG.info("Will use basic Linux customization (will customize hostname)");
// TODO: remove later, after all profiles are updated to use customization spec
final CustomizationSpec customization = new CustomizationSpec();
final CustomizationLinuxPrep linuxPrep = new CustomizationLinuxPrep();
final CustomizationLinuxOptions linuxOptions = new CustomizationLinuxOptions();
linuxPrep.setHostName(new CustomizationVirtualMachineName());
linuxPrep.setDomain(myDomain);
customization.setIdentity(linuxPrep);
customization.setOptions(linuxOptions);
customization.setGlobalIPSettings(new CustomizationGlobalIPSettings());
final CustomizationAdapterMapping mapping = new CustomizationAdapterMapping();
final CustomizationIPSettings ipSettings = new CustomizationIPSettings();
mapping.setAdapter(ipSettings);
ipSettings.setIp(new CustomizationDhcpIpGenerator());
customization.setNicSettingMap(new CustomizationAdapterMapping[]{mapping});
cloneSpec.setCustomization(customization);
}
try {
final Folder folder = findEntityByIdNameNullableOld(imageDetails.getFolderId(), Folder.class, datacenter);
if (folder != null) {
return vm.cloneVM_Task(folder, instance.getName(), cloneSpec);
} else {
String dcName = datacenter == null ? "root" : datacenter.getName();
throw new VmwareCheckedCloudException(
String.format("Unable to find folder %s in datacenter %s", imageDetails.getFolderId(), dcName)
);
}
} catch (RemoteException e) {
instance.setStatus(InstanceStatus.ERROR);
throw new VmwareCheckedCloudException(e);
}
}