Skip to content

Commit

Permalink
Merge pull request #38 from eddyhub/JENKINS-27305
Browse files Browse the repository at this point in the history
JENKINS-27305: Add support for distributed vswitches
  • Loading branch information
jswager committed Dec 11, 2015
2 parents c9e260c + a0cb51b commit af68018
Show file tree
Hide file tree
Showing 6 changed files with 251 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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();
Expand Down Expand Up @@ -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);
}
}
}
}
97 changes: 97 additions & 0 deletions src/main/java/org/jenkinsci/plugins/vsphere/tools/VSphere.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,28 @@ limitations under the License.
<f:textbox />
</f:entry>

<f:entry title="${%Network Port Group}" field="portGroup">
<f:textbox />
</f:entry>
<f:block>
<table>
<f:optionalBlock name="standardSwitch" title="Configure VMWare Standard Switch"
inline="true" checked="${instance.standardSwitch}">
<f:entry title="${%Network Port Group}" field="portGroup">
<f:textbox />
</f:entry>
</f:optionalBlock>
</table>
</f:block>

<f:block>
<table>
<f:optionalBlock name="distributedSwitch" title="Configure VMWare Distributed Switch"
inline="true" checked="${instance.distributedSwitch}">
<f:entry title="${%Distributed Port Group}" field="distributedPortGroup">
<f:textbox />
</f:entry>
<f:entry title="${%Distributed Port ID}" field="distributedPortId">
<f:textbox />
</f:entry>
</f:optionalBlock>
</table>
</f:block>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
Specifies the Distributed Switch Port Group.
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
Port Id to be used from the specified Distributed Switch Port Group.
</div>

0 comments on commit af68018

Please sign in to comment.