diff --git a/src/main/java/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters.java b/src/main/java/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters.java index 2bbdf558..ef39fc86 100644 --- a/src/main/java/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters.java +++ b/src/main/java/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters.java @@ -15,6 +15,9 @@ package org.jenkinsci.plugins.vsphere.builders; import com.vmware.vim25.*; +import com.vmware.vim25.mo.DistributedVirtualPortgroup; +import com.vmware.vim25.mo.DistributedVirtualSwitch; +import com.vmware.vim25.mo.Network; import hudson.EnvVars; import hudson.Extension; import hudson.Launcher; @@ -36,33 +39,60 @@ public class ReconfigureNetworkAdapters extends ReconfigureStep { private final DeviceAction deviceAction; private final String deviceLabel; private final String macAddress; + private final boolean standardSwitch; private final String portGroup; + private final boolean distributedSwitch; + private final String distributedPortGroup; + private final String distributedPortId; - @DataBoundConstructor - public ReconfigureNetworkAdapters(DeviceAction deviceAction, String deviceLabel, String macAddress, String portGroup) throws VSphereException { - this.deviceAction = deviceAction; + @DataBoundConstructor + public ReconfigureNetworkAdapters(DeviceAction deviceAction, String deviceLabel, String macAddress, + boolean standardSwitch,String portGroup, boolean distributedSwitch, + String distributedPortGroup, String distributedPortId) throws VSphereException { + + this.deviceAction = deviceAction; this.deviceLabel = deviceLabel; this.macAddress = macAddress; - this.portGroup = portGroup; - } + this.standardSwitch = standardSwitch; + this.portGroup = standardSwitch ? portGroup : null; + this.distributedSwitch = distributedSwitch; + this.distributedPortGroup = distributedSwitch ? distributedPortGroup : null; + this.distributedPortId = distributedSwitch ? distributedPortId : null; + } public DeviceAction getDeviceAction() { return deviceAction; } - public String getDeviceLabel() { - return deviceLabel; - } + public String getDeviceLabel() { + return deviceLabel; + } public String getMacAddress() { return macAddress; } + public boolean isStandardSwitch() { + return standardSwitch; + } + + public boolean isDistributedSwitch() { + return distributedSwitch; + } + public String getPortGroup() { return portGroup; } - public boolean perform(final AbstractBuild build, final Launcher launcher, final BuildListener listener) throws VSphereException { + public String getDistributedPortGroup() { + return distributedPortGroup; + } + + public String getDistributedPortId() { + return distributedPortId; + } + + public boolean perform(final AbstractBuild build, final Launcher launcher, final BuildListener listener) throws VSphereException { PrintStream jLogger = listener.getLogger(); EnvVars env; @@ -75,6 +105,8 @@ public boolean perform(final AbstractBuild build, final Launcher launcher, String expandedDeviceLabel = env.expand(deviceLabel); String expandedMacAddress = env.expand(macAddress); String expandedPortGroup = env.expand(portGroup); + String expandedDistributedPortGroup = env.expand(distributedPortGroup); + String expandedDistributedPortId = env.expand(distributedPortId); VSphereLogger.vsLogger(jLogger, "Preparing reconfigure: "+ deviceAction.getLabel() +" Network Adapter \"" + expandedDeviceLabel + "\""); VirtualEthernetCard vEth = null; @@ -101,11 +133,66 @@ public boolean perform(final AbstractBuild build, final Launcher launcher, vEth.setMacAddress(expandedMacAddress); } + + // extract backing from ethernet virtual card, always available + VirtualDeviceBackingInfo virtualDeviceBackingInfo = vEth.getBacking(); + // change our port group - if (!expandedPortGroup.isEmpty()) { + if (standardSwitch && !expandedPortGroup.isEmpty()) { VSphereLogger.vsLogger(jLogger, "Reconfiguring Network Port Group -> " + expandedPortGroup); - VirtualEthernetCardNetworkBackingInfo backing = (VirtualEthernetCardNetworkBackingInfo) vEth.getBacking(); - backing.deviceName = expandedPortGroup; + + if (virtualDeviceBackingInfo instanceof VirtualEthernetCardNetworkBackingInfo) { + VirtualEthernetCardNetworkBackingInfo backing = (VirtualEthernetCardNetworkBackingInfo) virtualDeviceBackingInfo; + + Network networkPortGroup = getVsphere().getNetworkPortGroupByName(getVM(), expandedPortGroup); + if (networkPortGroup != null) { + backing.deviceName = expandedPortGroup; + } + else { + VSphereLogger.vsLogger(jLogger, "Failed to find Network for Port Group -> " + expandedPortGroup); + } + } + else { + VSphereLogger.vsLogger(jLogger, "Network Device -> " + expandedDeviceLabel + " isn't standard switch"); + } + } + // change out distributed switch port group + else if (distributedSwitch && !expandedDistributedPortGroup.isEmpty()) { + VSphereLogger.vsLogger(jLogger, "Reconfiguring Distributed Switch Port Group -> " + expandedDistributedPortGroup + + " Port Id -> " + expandedDistributedPortId); + + if (virtualDeviceBackingInfo instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo) { + + VirtualEthernetCardDistributedVirtualPortBackingInfo virtualEthernetCardDistributedVirtualPortBackingInfo = + (VirtualEthernetCardDistributedVirtualPortBackingInfo) virtualDeviceBackingInfo; + + DistributedVirtualPortgroup distributedVirtualPortgroup = + getVsphere().getDistributedVirtualPortGroupByName(getVM(), expandedDistributedPortGroup); + + if (distributedVirtualPortgroup != null) { + DistributedVirtualSwitch distributedVirtualSwitch = + getVsphere().getDistributedVirtualSwitchByPortGroup(distributedVirtualPortgroup); + + DistributedVirtualSwitchPortConnection distributedVirtualSwitchPortConnection = + new DistributedVirtualSwitchPortConnection(); + + distributedVirtualSwitchPortConnection.setSwitchUuid(distributedVirtualSwitch.getUuid()); + distributedVirtualSwitchPortConnection.setPortgroupKey(distributedVirtualPortgroup.getKey()); + distributedVirtualSwitchPortConnection.setPortKey(expandedDistributedPortId); + + virtualEthernetCardDistributedVirtualPortBackingInfo.setPort(distributedVirtualSwitchPortConnection); + + VSphereLogger.vsLogger(jLogger, "Distributed Switch Port Group -> " + expandedDistributedPortGroup + + "Port Id -> " + expandedDistributedPortId + " successfully configured!"); + } + else { + VSphereLogger.vsLogger(jLogger, "Failed to find Distributed Virtual Portgroup for Port Group -> " + + expandedDistributedPortGroup); + } + } + else { + VSphereLogger.vsLogger(jLogger, "Network Device -> " + expandedDeviceLabel + " isn't distributed switch"); + } } VirtualDeviceConfigSpec vdspec = new VirtualDeviceConfigSpec(); @@ -140,33 +227,38 @@ private VirtualEthernetCard findNetworkDeviceByLabel(VirtualDevice[] devices, St return null; } - @Extension - public static final class ReconfigureNetworkAdaptersDescriptor extends ReconfigureStepDescriptor { + @Extension + public static final class ReconfigureNetworkAdaptersDescriptor extends ReconfigureStepDescriptor { - public ReconfigureNetworkAdaptersDescriptor() { - load(); - } + public ReconfigureNetworkAdaptersDescriptor() { + load(); + } public FormValidation doCheckMacAddress(@QueryParameter String value) - throws IOException, ServletException { + throws IOException, ServletException { if (value.length() == 0) return FormValidation.error(Messages.validation_required("the MAC Address")); return FormValidation.ok(); } - @Override - public String getDisplayName() { - return Messages.vm_title_ReconfigureNetworkAdapter(); - } + @Override + public String getDisplayName() { + return Messages.vm_title_ReconfigureNetworkAdapter(); + } - public FormValidation doTestData(@QueryParameter DeviceAction deviceAction, @QueryParameter String deviceLabel, - @QueryParameter String macAddress, @QueryParameter String portGroup) { - try { - return doCheckMacAddress(macAddress); - } catch (Exception e) { - throw new RuntimeException(e); - } - } + public FormValidation doTestData(@QueryParameter DeviceAction deviceAction, @QueryParameter String deviceLabel, + @QueryParameter String macAddress, @QueryParameter boolean standardSwitch, + @QueryParameter String portGroup, @QueryParameter boolean distributedSwitch, + @QueryParameter String distributedPortGroup, @QueryParameter String distributedPortId) { + try { + if (standardSwitch && distributedSwitch) { + return FormValidation.error(Messages.validation_wrongSwitchSelection()); + } + return doCheckMacAddress(macAddress); + } catch (Exception e) { + throw new RuntimeException(e); + } } + } } diff --git a/src/main/java/org/jenkinsci/plugins/vsphere/tools/VSphere.java b/src/main/java/org/jenkinsci/plugins/vsphere/tools/VSphere.java index df5704e1..3e17e424 100644 --- a/src/main/java/org/jenkinsci/plugins/vsphere/tools/VSphere.java +++ b/src/main/java/org/jenkinsci/plugins/vsphere/tools/VSphere.java @@ -48,6 +48,10 @@ import com.vmware.vim25.mo.Task; import com.vmware.vim25.mo.VirtualMachine; import com.vmware.vim25.mo.VirtualMachineSnapshot; +import com.vmware.vim25.mo.Datacenter; +import com.vmware.vim25.mo.Network; +import com.vmware.vim25.mo.DistributedVirtualPortgroup; +import com.vmware.vim25.mo.DistributedVirtualSwitch; public class VSphere { private final URL url; @@ -786,6 +790,99 @@ public void suspendVm(VirtualMachine vm) throws VSphereException{ throw new VSphereException("Machine could not be suspended!"); } + /** + * Private helper functions that finds the datanceter a VirtualMachine belongs to + * @param managedEntity - VM object + * @return returns Datacenter object + */ + private Datacenter getDataCenter(ManagedEntity managedEntity) + { + if (managedEntity != null) { + ManagedEntity parent = managedEntity.getParent(); + if (parent.getMOR().getType().equals("Datacenter")) { + return (Datacenter) parent; + } else { + return getDataCenter(managedEntity.getParent()); + } + } else { + return null; + } + } + + /** + * Find Distributed Virtual Port Group name in the same Datacenter as the VM + * @param virtualMachine - VM object + * @param name - the name of the Port Group + * @return returns DistributedVirtualPortgroup object for the provided vDS PortGroup + * @throws VSphereException + */ + public Network getNetworkPortGroupByName(VirtualMachine virtualMachine, + String name) throws VSphereException + { + try { + Datacenter datacenter = getDataCenter(virtualMachine); + for (Network network : datacenter.getNetworks()) + { + if (network instanceof Network && + (name.isEmpty() || network.getName().contentEquals(name))) + { + return network; + } + } + } catch (Exception e) { + throw new VSphereException(e); + } + return null; + } + + /** + * Find Distributed Virtual Port Group name in the same Datacenter as the VM + * @param virtualMachine - VM object + * @param name - the name of the Port Group + * @return returns DistributedVirtualPortgroup object for the provided vDS PortGroup + * @throws VSphereException + */ + public DistributedVirtualPortgroup getDistributedVirtualPortGroupByName(VirtualMachine virtualMachine, + String name) throws VSphereException + { + try { + Datacenter datacenter = getDataCenter(virtualMachine); + for (Network network : datacenter.getNetworks()) + { + if (network instanceof DistributedVirtualPortgroup && + (name.isEmpty() || network.getName().contentEquals(name))) + { + return (DistributedVirtualPortgroup)network; + } + } + } catch (Exception e) { + throw new VSphereException(e); + } + return null; + } + + /** + * Find Distributed Virtual Switch from the provided Distributed Virtual Portgroup + * @param distributedVirtualPortgroup - DistributedVirtualPortgroup object for the provided vDS PortGroup + * @return returns DistributedVirtualSwitch object that represents the vDS Switch + * @throws VSphereException + */ + public DistributedVirtualSwitch getDistributedVirtualSwitchByPortGroup( + DistributedVirtualPortgroup distributedVirtualPortgroup) throws VSphereException + { + try + { + ManagedObjectReference managedObjectReference = new ManagedObjectReference(); + managedObjectReference.setType("DistributedVirtualSwitch"); + managedObjectReference.setVal(distributedVirtualPortgroup.getConfig().getDistributedVirtualSwitch().getVal()); + return new DistributedVirtualSwitch(getServiceInstance().getServerConnection(), managedObjectReference); + } + catch (Exception e) + { + throw new VSphereException(e); + } + } + private void logMessage(PrintStream jLogger, String message) { if (jLogger != null) { VSphereLogger.vsLogger(jLogger, message); diff --git a/src/main/resources/org/jenkinsci/plugins/vsphere/builders/Messages.properties b/src/main/resources/org/jenkinsci/plugins/vsphere/builders/Messages.properties index 6a5bf96a..efd0fbbb 100644 --- a/src/main/resources/org/jenkinsci/plugins/vsphere/builders/Messages.properties +++ b/src/main/resources/org/jenkinsci/plugins/vsphere/builders/Messages.properties @@ -14,6 +14,7 @@ vm.title.ReconfigureNetworkAdapter=Edit Network Adapter vm.title.ReconfigureCpu=Edit CPU vm.title.ReconfigureMemory=Edit Memory vm.title.ReconfigureDisk=Add a disk +vm.title.ReconfigureAnnotation=Add an annotation vm.title.Rename=Rename VM vm.title.RenameSnapshot=Rename Snapshot vm.title.TakeSnapshot=Take Snapshot @@ -41,3 +42,4 @@ console.usingServerConfig=Attempting to use server configuration: "{0}" validation.serverExistence=Server does not exist in global config! Please re-save your job configuration. validation.instanceNotFound=Could not find vSphere Cloud instance "{0}"! +validation.wrongSwitchSelection=Cannot configure both Standard Switch and Distributed Switch for the same network device \ No newline at end of file diff --git a/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/config.jelly b/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/config.jelly index db5ee51a..000b9f06 100644 --- a/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/config.jelly +++ b/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/config.jelly @@ -30,7 +30,28 @@ limitations under the License. - - - + + + + + + + +
+
+ + + + + + + + + + + +
+
diff --git a/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/help-distributedPortGroup.html b/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/help-distributedPortGroup.html new file mode 100644 index 00000000..c9840091 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/help-distributedPortGroup.html @@ -0,0 +1,3 @@ +
+ Specifies the Distributed Switch Port Group. +
diff --git a/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/help-distributedPortId.html b/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/help-distributedPortId.html new file mode 100644 index 00000000..be52716e --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/vsphere/builders/ReconfigureNetworkAdapters/help-distributedPortId.html @@ -0,0 +1,3 @@ +
+ Port Id to be used from the specified Distributed Switch Port Group. +