Skip to content

Commit

Permalink
Merge pull request #85 from pjdarton/robustness
Browse files Browse the repository at this point in the history
[JENKINS-44796] Robustness improvements
  • Loading branch information
pjdarton committed Aug 21, 2017
2 parents 1701651 + d53ebf6 commit 894d449
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 13 deletions.
33 changes: 25 additions & 8 deletions src/main/java/org/jenkinsci/plugins/vSphereCloudSlaveTemplate.java
Expand Up @@ -357,9 +357,19 @@ protected Object readResolve() {
}

public vSphereCloudProvisionedSlave provision(final String cloneName, final TaskListener listener) throws VSphereException, FormException, IOException, InterruptedException {
vSphereCloudProvisionedSlave slave = null;
final PrintStream logger = listener.getLogger();
final Map<String, String> resolvedExtraConfigParameters = calculateExtraConfigParameters(cloneName, listener);
final VSphere vSphere = getParent().vSphereInstance();
final vSphereCloudProvisionedSlave slave;
try {
slave = provision(cloneName, logger, resolvedExtraConfigParameters, vSphere);
} finally {
vSphere.disconnect();
}
return slave;
}

private vSphereCloudProvisionedSlave provision(final String cloneName, final PrintStream logger, final Map<String, String> resolvedExtraConfigParameters, final VSphere vSphere) throws VSphereException, FormException, IOException {
final boolean POWER_ON = true;
final boolean useCurrentSnapshot;
final String snapshotToUse;
Expand All @@ -377,7 +387,7 @@ public vSphereCloudProvisionedSlave provision(final String cloneName, final Task
snapshotToUse = null;
}
try {
vSphere.cloneOrDeployVm(cloneName, this.masterImageName, this.linkedClone, this.resourcePool, this.cluster, this.datastore, this.folder, useCurrentSnapshot, snapshotToUse, POWER_ON, this.customizationSpec, logger);
vSphere.cloneOrDeployVm(cloneName, this.masterImageName, this.linkedClone, this.resourcePool, this.cluster, this.datastore, this.folder, useCurrentSnapshot, snapshotToUse, POWER_ON, resolvedExtraConfigParameters, this.customizationSpec, logger);
LOGGER.log(Level.FINE, "Created new VM {0} from image {1}", new Object[]{ cloneName, this.masterImageName });
} catch (VSphereDuplicateException ex) {
final String vmJenkinsUrl = findWhichJenkinsThisVMBelongsTo(vSphere, cloneName);
Expand All @@ -392,13 +402,21 @@ public vSphereCloudProvisionedSlave provision(final String cloneName, final Task
LOGGER.log(Level.SEVERE, "VM {0} name clashes with one we wanted to use, but it doesn't belong to this Jenkins server: it belongs to {1}. You MUST reconfigure one of these Jenkins servers to use a different naming strategy so that we no longer get clashes within vSphere host {2}. i.e. change the cloneNamePrefix on one/both to ensure uniqueness.", new Object[]{ cloneName, vmJenkinsUrl, this.getParent().getVsHost() } );
throw ex;
}
} catch (VSphereException ex) {
// if anything else went wrong, attempt to tidy up
try {
vSphere.destroyVm(cloneName, false);
} catch (Exception logOnly) {
LOGGER.log(Level.SEVERE,
"Unable to create and power-on new VM " + cloneName + " (cloned from image "
+ this.masterImageName
+ ") and, worse, bits of the VM may still exist as the attempt to delete the remains also failed.",
logOnly);
}
throw ex;
}
vSphereCloudProvisionedSlave slave = null;
try {
final Map<String, String> resolvedExtraConfigParameters = calculateExtraConfigParameters(cloneName, listener);
if( !resolvedExtraConfigParameters.isEmpty() ) {
LOGGER.log(Level.FINE, "Provisioning slave {0} with guestinfo properties {1}", new Object[]{ cloneName, resolvedExtraConfigParameters });
vSphere.setExtraConfigParameters(cloneName, resolvedExtraConfigParameters);
}
final ComputerLauncher configuredLauncher = determineLauncher(vSphere, cloneName);
final RetentionStrategy<?> configuredStrategy = determineRetention();
final String snapshotNameForLauncher = ""; /* we don't make the launcher do anything with snapshots because our clone won't be created with any */
Expand All @@ -410,7 +428,6 @@ public vSphereCloudProvisionedSlave provision(final String cloneName, final Task
vSphere.destroyVm(cloneName, false);
}
}
vSphere.disconnect();
return slave;
}

Expand Down
29 changes: 24 additions & 5 deletions src/main/java/org/jenkinsci/plugins/vsphere/tools/VSphere.java
Expand Up @@ -127,8 +127,9 @@ public void disconnect() {
public void deployVm(String cloneName, String sourceName, boolean linkedClone, String resourcePoolName, String cluster, String datastoreName, String folderName, boolean powerOn, String customizationSpec, PrintStream jLogger) throws VSphereException {
final boolean useCurrentSnapshotIsFALSE = false;
final String namedSnapshotIsNULL = null;
final Map<String, String> extraConfigParameters = null;
logMessage(jLogger, "Deploying new vm \""+ cloneName + "\" from template \""+sourceName+"\"");
cloneOrDeployVm(cloneName, sourceName, linkedClone, resourcePoolName, cluster, datastoreName, folderName, useCurrentSnapshotIsFALSE, namedSnapshotIsNULL, powerOn, customizationSpec, jLogger);
cloneOrDeployVm(cloneName, sourceName, linkedClone, resourcePoolName, cluster, datastoreName, folderName, useCurrentSnapshotIsFALSE, namedSnapshotIsNULL, powerOn, extraConfigParameters, customizationSpec, jLogger);
}

/**
Expand All @@ -149,8 +150,9 @@ public void deployVm(String cloneName, String sourceName, boolean linkedClone, S
public void cloneVm(String cloneName, String sourceName, boolean linkedClone, String resourcePoolName, String cluster, String datastoreName, String folderName, boolean powerOn, String customizationSpec, PrintStream jLogger) throws VSphereException {
final boolean useCurrentSnapshotIsTRUE = true;
final String namedSnapshotIsNULL = null;
final Map<String, String> extraConfigParameters = null;
logMessage(jLogger, "Creating a " + (linkedClone?"shallow":"deep") + " clone of \"" + sourceName + "\" to \"" + cloneName + "\"");
cloneOrDeployVm(cloneName, sourceName, linkedClone, resourcePoolName, cluster, datastoreName, folderName, useCurrentSnapshotIsTRUE, namedSnapshotIsNULL, powerOn, customizationSpec, jLogger);
cloneOrDeployVm(cloneName, sourceName, linkedClone, resourcePoolName, cluster, datastoreName, folderName, useCurrentSnapshotIsTRUE, namedSnapshotIsNULL, powerOn, extraConfigParameters, customizationSpec, jLogger);
}

/**
Expand Down Expand Up @@ -183,14 +185,22 @@ public void cloneVm(String cloneName, String sourceName, boolean linkedClone, St
* @param powerOn
* If true then the new VM will be switched on after it has been
* created.
* @param extraConfigParameters
* (Optional) parameters to set in the VM's "extra config"
* object. This data can then be read back at a later stage.In
* the case of parameters whose name starts "guestinfo.", the
* parameter can be read by the VMware Tools on the client OS.
* e.g. a variable named "guestinfo.Foo" with value "Bar" could
* be read on the guest using the command-line
* <tt>vmtoolsd --cmd "info-get guestinfo.Foo"</tt>.
* @param customizationSpec
* (Optional) Customization spec to use for this VM, or null
* @param jLogger
* Where to log to.
* @throws VSphereException
* if anything goes wrong.
*/
public void cloneOrDeployVm(String cloneName, String sourceName, boolean linkedClone, String resourcePoolName, String cluster, String datastoreName, String folderName, boolean useCurrentSnapshot, final String namedSnapshot, boolean powerOn, String customizationSpec, PrintStream jLogger) throws VSphereException {
public void cloneOrDeployVm(String cloneName, String sourceName, boolean linkedClone, String resourcePoolName, String cluster, String datastoreName, String folderName, boolean useCurrentSnapshot, final String namedSnapshot, boolean powerOn, Map<String, String> extraConfigParameters, String customizationSpec, PrintStream jLogger) throws VSphereException {
try {
final VirtualMachine sourceVm = getVmByName(sourceName);
if (sourceVm==null) {
Expand Down Expand Up @@ -227,7 +237,11 @@ public void cloneOrDeployVm(String cloneName, String sourceName, boolean linkedC
logMessage(jLogger, "Clone of " + sourceType + " \"" + sourceName + "\" will be based on current snapshot \"" + currentSnapShot.toString() + "\".");
cloneSpec.setSnapshot(currentSnapShot.getMOR());
}

if (extraConfigParameters != null && !extraConfigParameters.isEmpty()) {
logMessage(jLogger, "Clone of " + sourceType + " \"" + sourceName + "\" will have extra configuration parameters " + extraConfigParameters + ".");
VirtualMachineConfigSpec cs = createVMConfigSpecFromExtraConfigParameters(extraConfigParameters);
cloneSpec.setConfig(cs);
}
if (customizationSpec != null && customizationSpec.length() > 0) {
logMessage(jLogger, "Clone of " + sourceType + " \"" + sourceName + "\" will use customization specification \"" + customizationSpec + "\".");
CustomizationSpecItem spec = getCustomizationSpecByName(customizationSpec);
Expand Down Expand Up @@ -1052,6 +1066,11 @@ public DistributedVirtualSwitch getDistributedVirtualSwitchByPortGroup(
* If an error occurred.
*/
public void setExtraConfigParameters(String vmName, Map<String, String> parameters) throws VSphereException {
VirtualMachineConfigSpec cs = createVMConfigSpecFromExtraConfigParameters(parameters);
reconfigureVm(vmName, cs);
}

private static VirtualMachineConfigSpec createVMConfigSpecFromExtraConfigParameters(Map<String, String> parameters) {
VirtualMachineConfigSpec cs = new VirtualMachineConfigSpec();
OptionValue[] ourOptionValues = new OptionValue[parameters.size()];
List<OptionValue> optionValues = new ArrayList<>();
Expand All @@ -1065,7 +1084,7 @@ public void setExtraConfigParameters(String vmName, Map<String, String> paramete
ourOptionValues[i] = optionValues.get(i);
}
cs.setExtraConfig(ourOptionValues);
reconfigureVm(vmName, cs);
return cs;
}

private void logMessage(PrintStream jLogger, String message) {
Expand Down

0 comments on commit 894d449

Please sign in to comment.