Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JENKINS-27305: Add support for distributed vswitches #38

Merged
merged 1 commit into from
Dec 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -758,6 +762,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>