You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by hu...@apache.org on 2013/07/12 12:19:19 UTC

[1/4] git commit: updated refs/heads/master to 2691970

Updated Branches:
  refs/heads/master 5dd1a1dd8 -> 2691970f2


CLOUDSTACK-728 Rewrite support for lswitch connected nics on both standard and distributed switches.

Fix the name of the interface id in extra config, so the nic is found up using the nic uuid instead of the vm id.

getVlanInfo should return null when the nic is plugged on a Lswitch network.

On a distributed portgroup all vms should be connected to a single
portgroup and set a specific vlan on the port. On a standard switch each nic should have its own portgroup with a dedicated vlan (not related to CS vlans)


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/392bbcc7
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/392bbcc7
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/392bbcc7

Branch: refs/heads/master
Commit: 392bbcc737ec8622d4101df783bc947266ff3dfe
Parents: 5dd1a1d
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Wed Jul 3 14:58:44 2013 +0200
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Fri Jul 12 12:18:07 2013 +0200

----------------------------------------------------------------------
 .../vmware/manager/VmwareManagerImpl.java       |   2 +-
 .../vmware/resource/VmwareResource.java         | 157 ++++++++++++++++++-
 .../vmware/mo/HypervisorHostHelper.java         |  69 ++++++--
 .../hypervisor/vmware/mo/VirtualMachineMO.java  |  76 ++++-----
 4 files changed, 251 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/392bbcc7/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
index c872e93..9eb6d34 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
@@ -352,7 +352,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
         }
         s_logger.info("Preparing network on host " + hostMo.getContext().toString() + " for " + privateTrafficLabel);
         //The management network is probably always going to be a physical network with vlans, so assume BroadcastDomainType VLAN
-        HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false, BroadcastDomainType.Vlan);
+        HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false, BroadcastDomainType.Vlan, null);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/392bbcc7/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 1f54f9c..57f3121 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -265,6 +265,7 @@ import com.cloud.hypervisor.vmware.mo.CustomFieldsManagerMO;
 import com.cloud.hypervisor.vmware.mo.DatacenterMO;
 import com.cloud.hypervisor.vmware.mo.DatastoreMO;
 import com.cloud.hypervisor.vmware.mo.DiskControllerType;
+import com.cloud.hypervisor.vmware.mo.DistributedVirtualSwitchMO;
 import com.cloud.hypervisor.vmware.mo.FeatureKeyConstants;
 import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO;
 import com.cloud.hypervisor.vmware.mo.HostFirewallSystemMO;
@@ -319,6 +320,70 @@ import com.cloud.vm.VirtualMachine.State;
 import com.cloud.vm.VirtualMachineName;
 import com.cloud.vm.VmDetailConstants;
 
+import com.google.gson.Gson;
+import com.vmware.vim25.AboutInfo;
+import com.vmware.vim25.BoolPolicy;
+import com.vmware.vim25.ClusterDasConfigInfo;
+import com.vmware.vim25.ComputeResourceSummary;
+import com.vmware.vim25.DVPortConfigInfo;
+import com.vmware.vim25.DVPortConfigSpec;
+import com.vmware.vim25.DVPortSetting;
+import com.vmware.vim25.DatastoreSummary;
+import com.vmware.vim25.DistributedVirtualPort;
+import com.vmware.vim25.DistributedVirtualSwitchPortConnection;
+import com.vmware.vim25.DistributedVirtualSwitchPortCriteria;
+import com.vmware.vim25.DynamicProperty;
+import com.vmware.vim25.GuestInfo;
+import com.vmware.vim25.GuestOsDescriptor;
+import com.vmware.vim25.HostCapability;
+import com.vmware.vim25.HostFirewallInfo;
+import com.vmware.vim25.HostFirewallRuleset;
+import com.vmware.vim25.HostHostBusAdapter;
+import com.vmware.vim25.HostInternetScsiTargetTransport;
+import com.vmware.vim25.HostScsiTopology;
+import com.vmware.vim25.HostInternetScsiHba;
+import com.vmware.vim25.HostInternetScsiHbaAuthenticationProperties;
+import com.vmware.vim25.HostInternetScsiHbaStaticTarget;
+import com.vmware.vim25.HostScsiDisk;
+import com.vmware.vim25.HostScsiTopologyInterface;
+import com.vmware.vim25.HostScsiTopologyLun;
+import com.vmware.vim25.HostScsiTopologyTarget;
+import com.vmware.vim25.ManagedObjectReference;
+import com.vmware.vim25.ObjectContent;
+import com.vmware.vim25.OptionValue;
+import com.vmware.vim25.PerfCounterInfo;
+import com.vmware.vim25.PerfEntityMetric;
+import com.vmware.vim25.PerfEntityMetricBase;
+import com.vmware.vim25.PerfMetricId;
+import com.vmware.vim25.PerfMetricIntSeries;
+import com.vmware.vim25.PerfMetricSeries;
+import com.vmware.vim25.PerfQuerySpec;
+import com.vmware.vim25.PerfSampleInfo;
+import com.vmware.vim25.RuntimeFaultFaultMsg;
+import com.vmware.vim25.ToolsUnavailableFaultMsg;
+import com.vmware.vim25.VMwareDVSPortSetting;
+import com.vmware.vim25.VimPortType;
+import com.vmware.vim25.VirtualDevice;
+import com.vmware.vim25.VirtualDeviceBackingInfo;
+import com.vmware.vim25.VirtualDeviceConfigSpec;
+import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
+import com.vmware.vim25.VirtualDisk;
+import com.vmware.vim25.VirtualEthernetCard;
+import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
+import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
+import com.vmware.vim25.VirtualLsiLogicController;
+import com.vmware.vim25.VirtualMachineConfigOption;
+import com.vmware.vim25.VirtualMachineConfigSpec;
+import com.vmware.vim25.VirtualMachineFileInfo;
+import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
+import com.vmware.vim25.VirtualMachinePowerState;
+import com.vmware.vim25.VirtualMachineRelocateSpec;
+import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
+import com.vmware.vim25.VirtualMachineRuntimeInfo;
+import com.vmware.vim25.VirtualSCSISharing;
+import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
+
+
 public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService {
     private static final Logger s_logger = Logger.getLogger(VmwareResource.class);
 
@@ -1803,7 +1868,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
          */
         if (VirtualSwitchType.StandardVirtualSwitch == vSwitchType) {
             networkInfo = HypervisorHostHelper.prepareNetwork(_publicTrafficInfo.getVirtualSwitchName(), "cloud.public",
-                    vmMo.getRunningHost(), vlanId, null, null, _ops_timeout, true, BroadcastDomainType.Vlan);
+                    vmMo.getRunningHost(), vlanId, null, null, _ops_timeout, true, BroadcastDomainType.Vlan, null);
         } else {
             networkInfo = HypervisorHostHelper.prepareNetwork(_publicTrafficInfo.getVirtualSwitchName(), "cloud.public",
                     vmMo.getRunningHost(), vlanId, null, null, null, _ops_timeout, vSwitchType, _portsPerDvPortGroup, null, false, BroadcastDomainType.Vlan);
@@ -2807,13 +2872,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             extraOptions.add(newVal);
             
             /**
-             * Extra Config : nvp.iface-id<num> = uuid
+             * Extra Config : nvp.iface-id.<num> = uuid
              *  - Required for Nicira NVP integration
              */
             int nicNum = 0;
             for (NicTO nicTo : sortNicsByDeviceId(nics)) {
                 newVal = new OptionValue();
-                newVal.setKey("nvp.iface-id" + nicNum);
+                newVal.setKey("nvp.iface-id." + nicNum);
                 newVal.setValue(nicTo.getUuid());
                 extraOptions.add(newVal);
                 nicNum++;
@@ -2837,9 +2902,86 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
             vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMask));
 
+            int nicIndex = 0;
+            for (NicTO nicTo : sortNicsByDeviceId(nics)) {
+                s_logger.debug("Checking for port configuration on NIC device : " + nicTo.toString());
+                if (nicTo.getBroadcastType() == BroadcastDomainType.Lswitch) {
+                    // We need to create a port with a unique vlan and pass the key to the nic device
+                    s_logger.debug("Nic " + nicTo.toString() + " needs to be configured for NVP");
+                    VirtualDevice nicVirtualDevice = vmMo.getNicDeviceByIndex(nicIndex);
+                    if (nicVirtualDevice == null) {
+                        throw new Exception("Failed to find a VirtualDevice for nic " + nicIndex); //FIXME Generic exceptions are bad
+                    }
+                    VirtualDeviceBackingInfo backing = nicVirtualDevice.getBacking();
+                    if (backing instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo) {
+                        VirtualEthernetCardDistributedVirtualPortBackingInfo portInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo) backing;
+                        DistributedVirtualSwitchPortConnection port = portInfo.getPort();
+                        String portKey = port.getPortKey();
+                        String portGroupKey = port.getPortgroupKey();
+                        String dvSwitchUuid = port.getSwitchUuid();
+                        
+                        s_logger.debug("NIC " + nicTo.toString() + " is connected to dvSwitch " + dvSwitchUuid + " pg " + portGroupKey + " port " + portKey);
+                        
+                        ManagedObjectReference dvSwitchManager = vmMo.getContext().getVimClient().getServiceContent().getDvSwitchManager();
+                        ManagedObjectReference dvSwitch = vmMo.getContext().getVimClient().getService().queryDvsByUuid(dvSwitchManager, dvSwitchUuid);
+                        
+                        DistributedVirtualSwitchPortCriteria criteria = new DistributedVirtualSwitchPortCriteria();
+                        criteria.setInside(true);
+                        criteria.getPortgroupKey().add(portGroupKey);
+                        criteria.getPortKey().add(portKey);
+                        List<DistributedVirtualPort> dvPorts = vmMo.getContext().getVimClient().getService().fetchDVPorts(dvSwitch, criteria);
+                        
+                        if (dvPorts.isEmpty()) {
+                            throw new Exception("Empty port list from dvSwitch for nic " + nicTo.toString());
+                        } else if (dvPorts.size() > 1) {
+                            throw new Exception("Expected only one port in the list from dvSwitch for nic " + nicTo.toString());
+                        }
+
+                        DistributedVirtualPort dvPort = dvPorts.get(0);
+                        DVPortConfigInfo dvPortConfigInfo = dvPort.getConfig();
+                        VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPortConfigInfo.getSetting();
+                        
+                        VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan();
+                        BoolPolicy blocked = settings.getBlocked();
+                        if (blocked.isValue() == Boolean.TRUE) {
+                            s_logger.debug("Port is blocked, we need to set a vlanid and unblock"); 
+                            DVPortConfigSpec dvPortConfigSpec = new DVPortConfigSpec();
+                            VMwareDVSPortSetting edittedSettings = new VMwareDVSPortSetting();
+                            // Unblock
+                            blocked.setValue(Boolean.FALSE);
+                            blocked.setInherited(Boolean.FALSE);
+                            edittedSettings.setBlocked(blocked);
+                            // Set vlan
+                            vlanId.setVlanId(100); //FIXME should be a determined based on usage
+                            vlanId.setInherited(false);
+                            edittedSettings.setVlan(vlanId);
+                            
+                            dvPortConfigSpec.setSetting(edittedSettings);
+                            dvPortConfigSpec.setOperation("edit");
+                            dvPortConfigSpec.setKey(portKey);
+                            List<DVPortConfigSpec> dvPortConfigSpecs = new ArrayList<DVPortConfigSpec>();
+                            dvPortConfigSpecs.add(dvPortConfigSpec);
+                            ManagedObjectReference task = vmMo.getContext().getVimClient().getService().reconfigureDVPortTask(dvSwitch, dvPortConfigSpecs);
+                            if (!vmMo.getContext().getVimClient().waitForTask(task)) {
+                                s_logger.error("Failed to configure the dvSwitch port for nic " + nicTo.toString());
+                            }
+                        } else {
+                            s_logger.trace("Port already configured and set to vlan " + vlanId.getVlanId());
+                        }
+                    }
+                    else {
+                        s_logger.error("nic device backing is of type " + backing.getClass().getName());
+                        throw new Exception("Incompatible backing for a VirtualDevice for nic " + nicIndex); //FIXME Generic exceptions are bad
+                    }
+                }
+                nicIndex++;
+            }
+
             if (!vmMo.powerOn()) {
                 throw new Exception("Failed to start VM. vmName: " + vmName);
             }
+            
+
 
             state = State.Running;
             return new StartAnswer(cmd);
@@ -2971,7 +3113,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         if (nicTo.getBroadcastType() == BroadcastDomainType.Native) {
             return defaultVlan;
         }
-        if (nicTo.getBroadcastType() == BroadcastDomainType.Vlan || nicTo.getBroadcastType() == BroadcastDomainType.Pvlan) {
+        else if (nicTo.getBroadcastType() == BroadcastDomainType.Vlan || nicTo.getBroadcastType() == BroadcastDomainType.Pvlan) {
             if (nicTo.getBroadcastUri() != null) {
                 if (nicTo.getBroadcastType() == BroadcastDomainType.Vlan)
                     // For vlan, the broadcast uri is of the form vlan://<vlanid>
@@ -2983,6 +3125,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 s_logger.warn("BroadcastType is not claimed as VLAN or PVLAN, but without vlan info in broadcast URI. Use vlan info from labeling: " + defaultVlan);
                 return defaultVlan;
             }
+        } else if (nicTo.getBroadcastType() == BroadcastDomainType.Lswitch) {
+            // We don't need to set any VLAN id for an NVP logical switch
+            return null;
         }
 
         s_logger.warn("Unrecognized broadcast type in VmwareResource, type: " + nicTo.getBroadcastType().toString() + ". Use vlan info from labeling: " + defaultVlan);
@@ -3015,7 +3160,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         if (VirtualSwitchType.StandardVirtualSwitch == switchType) {
             networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix,
                     hostMo, getVlanInfo(nicTo, switchName.second()), nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout,
-                    !namePrefix.startsWith("cloud.private"), nicTo.getBroadcastType());
+                    !namePrefix.startsWith("cloud.private"), nicTo.getBroadcastType(), nicTo.getUuid());
         }
         else {
             String vlanId = getVlanInfo(nicTo, switchName.second());
@@ -3029,7 +3174,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 svlanId = getPvlanInfo(nicTo);
             }
             networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, vlanId, svlanId,
-                    nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, switchType,
+                    nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, switchType, 
                     _portsPerDvPortGroup, nicTo.getGateway(), configureVServiceInNexus, nicTo.getBroadcastType());
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/392bbcc7/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
index 9df7bc3..dc1486a 100755
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java
@@ -52,6 +52,7 @@ import com.vmware.vim25.DVSTrafficShapingPolicy;
 import com.vmware.vim25.DynamicProperty;
 import com.vmware.vim25.HostNetworkSecurityPolicy;
 import com.vmware.vim25.HostNetworkTrafficShapingPolicy;
+import com.vmware.vim25.HostPortGroup;
 import com.vmware.vim25.HostPortGroupSpec;
 import com.vmware.vim25.HostVirtualSwitch;
 import com.vmware.vim25.HttpNfcLeaseDeviceUrl;
@@ -467,8 +468,12 @@ public class HypervisorHostHelper {
                 throw new InvalidParameterException("Nexus Distributed Virtualswitch is not supported with BroadcastDomainType " + 
                         broadcastDomainType);
             }
-            // Fixed name for the port-group on the vApp vswitch
-            networkName = "br-int";
+            /** 
+             * Nicira NVP requires all vms to be connected to a single port-group.
+             * A unique vlan needs to be set per port. This vlan is specific to
+             * this implementation and has no reference to other vlans in CS
+             */
+            networkName = "br-int"; // FIXME Should be set via a configuration item in CS
             // No doubt about this, depending on vid=null to avoid lots of code below
             vid = null;
         } else {
@@ -508,8 +513,7 @@ public class HypervisorHostHelper {
 
             if (broadcastDomainType == BroadcastDomainType.Lswitch) {
                 if (!dataCenterMo.hasDvPortGroup(networkName)) {
-                    // It'a bad thing if the integration bridge port-group does not exist
-                    throw new InvalidParameterException("Unable to find port-group " + networkName + " on dvSwitch " + dvSwitchName);
+                    throw new InvalidParameterException("NVP integration port-group " + networkName + " does not exist on the DVS " + dvSwitchName);
                 }
                 bWaitPortGroupReady = false;
             } else {
@@ -856,7 +860,7 @@ public class HypervisorHostHelper {
 
     public static Pair<ManagedObjectReference, String> prepareNetwork(String vSwitchName, String namePrefix,
             HostMO hostMo, String vlanId, Integer networkRateMbps, Integer networkRateMulticastMbps,
-            long timeOutMs, boolean syncPeerHosts, BroadcastDomainType broadcastDomainType) throws Exception {
+            long timeOutMs, boolean syncPeerHosts, BroadcastDomainType broadcastDomainType, String nicUuid) throws Exception {
 
         HostVirtualSwitch vSwitch;
         if (vSwitchName == null) {
@@ -893,8 +897,11 @@ public class HypervisorHostHelper {
         }
 
         if (broadcastDomainType == BroadcastDomainType.Lswitch) {
-            // Fixed name for the port-group on the vApp vswitch
-            networkName = "br-int";
+            /** 
+             * Nicira NVP requires each vm to have its own port-group with a dedicated
+             * vlan. We'll set the name of the pg to the uuid of the nic.
+             */
+            networkName = nicUuid;
             // No doubt about this, depending on vid=null to avoid lots of code below
             vid = null;
         } else {
@@ -933,10 +940,12 @@ public class HypervisorHostHelper {
         boolean bWaitPortGroupReady = false;
         if (broadcastDomainType == BroadcastDomainType.Lswitch) {
             if (!hostMo.hasPortGroup(vSwitch, networkName)) {
-                // It'a bad thing if the integration bridge port-group does not exist
-                throw new InvalidParameterException("Unable to find port-group " + networkName + " on dvSwitch " + vSwitchName);
+                createNvpPortGroup(hostMo, vSwitch, networkName, shapingPolicy);
+                
+                bWaitPortGroupReady = true;
+            } else {
+                bWaitPortGroupReady = false;
             }
-            bWaitPortGroupReady = false;
         } else {
             if (!hostMo.hasPortGroup(vSwitch, networkName)) {
                 hostMo.createPortGroup(vSwitch, networkName, vid, secPolicy, shapingPolicy);
@@ -982,7 +991,7 @@ public class HypervisorHostHelper {
                                         try {
                                             if(s_logger.isDebugEnabled())
                                                 s_logger.debug("Prepare network on other host, vlan: " + vlanId + ", host: " + otherHostMo.getHostName());
-                                            prepareNetwork(vSwitchName, namePrefix, otherHostMo, vlanId, networkRateMbps, networkRateMulticastMbps, timeOutMs, false, broadcastDomainType);
+                                            prepareNetwork(vSwitchName, namePrefix, otherHostMo, vlanId, networkRateMbps, networkRateMulticastMbps, timeOutMs, false, broadcastDomainType, nicUuid);
                                         } catch(Exception e) {
                                             s_logger.warn("Unable to prepare network on other host, vlan: " + vlanId + ", host: " + otherHostMo.getHostName());
                                         }
@@ -1041,6 +1050,44 @@ public class HypervisorHostHelper {
 
         return true;
     }
+    
+    private static void createNvpPortGroup(HostMO hostMo, HostVirtualSwitch vSwitch, String networkName, HostNetworkTrafficShapingPolicy shapingPolicy) throws Exception {
+        /** 
+         * No portgroup created yet for this nic
+         * We need to find an unused vlan and create the pg
+         * The vlan is limited to this vSwitch and the NVP vAPP, 
+         * so no relation to the other vlans in use in CloudStack.
+         */
+        String vSwitchName = vSwitch.getName();
+        
+        // Find all vlanids that we have in use
+        List<Integer> usedVlans = new ArrayList<Integer>();
+        for (HostPortGroup pg : hostMo.getHostNetworkInfo().getPortgroup()) {
+           HostPortGroupSpec hpgs = pg.getSpec();
+           if (vSwitchName.equals(hpgs.getVswitchName()))
+               usedVlans.add(hpgs.getVlanId());
+        }
+        
+        // Find the first free vlanid
+        int nvpVlanId = 0;
+        for (nvpVlanId = 1; nvpVlanId < 4095; nvpVlanId++) {
+            if (! usedVlans.contains(nvpVlanId)) {
+                break;
+            }
+        }
+        if (nvpVlanId == 4095) {
+            throw new InvalidParameterException("No free vlan numbers on " + vSwitchName + " to create a portgroup for nic " + networkName);
+        }
+        
+        // Strict security policy
+        HostNetworkSecurityPolicy secPolicy = new HostNetworkSecurityPolicy();
+        secPolicy.setAllowPromiscuous(Boolean.FALSE);
+        secPolicy.setForgedTransmits(Boolean.FALSE);
+        secPolicy.setMacChanges(Boolean.FALSE);
+        
+        // Create a portgroup with the uuid of the nic and the vlanid found above
+        hostMo.createPortGroup(vSwitch, networkName, nvpVlanId, secPolicy, shapingPolicy);      
+    }
 
     public static ManagedObjectReference waitForNetworkReady(HostMO hostMo,
             String networkName, long timeOutMs) throws Exception {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/392bbcc7/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
----------------------------------------------------------------------
diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
index 5214f3d..e2dd789 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -2048,47 +2048,53 @@ public class VirtualMachineMO extends BaseMO {
 		return ++deviceNumber;
 	}
 
-	public VirtualDevice[] getNicDevices() throws Exception {
-		List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
-			getDynamicProperty(_mor, "config.hardware.device");
+	private List<VirtualDevice> getNicDevices(boolean sorted) throws Exception {
+        List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
+                getDynamicProperty(_mor, "config.hardware.device");
 
-		List<VirtualDevice> nics = new ArrayList<VirtualDevice>();
-		if(devices != null) {
-			for(VirtualDevice device : devices) {
-				if(device instanceof VirtualEthernetCard) {
-                    nics.add(device);
+            List<VirtualDevice> nics = new ArrayList<VirtualDevice>();
+            if(devices != null) {
+                for(VirtualDevice device : devices) {
+                    if(device instanceof VirtualEthernetCard) {
+                        nics.add(device);
+                    }
                 }
-			}
-		}
+            }
+            
+            if (sorted) {
+                Collections.sort(nics, new Comparator<VirtualDevice>() {
+                    @Override
+                    public int compare(VirtualDevice arg0, VirtualDevice arg1) {
+                        int unitNumber0 = arg0.getUnitNumber() != null ? arg0.getUnitNumber().intValue() : -1;
+                        int unitNumber1 = arg1.getUnitNumber() != null ? arg1.getUnitNumber().intValue() : -1;
+                        if(unitNumber0 < unitNumber1)
+                            return -1;
+                        else if(unitNumber0 > unitNumber1)
+                            return 1;
+                        return 0;
+                    }
+                });
+            }
+            
+            return nics;
+	}
 
-		return nics.toArray(new VirtualDevice[0]);
+	public VirtualDevice[] getNicDevices() throws Exception {
+		return getNicDevices(false).toArray(new VirtualDevice[0]);
+	}
+	
+	public VirtualDevice getNicDeviceByIndex(int index) throws Exception {
+	    List<VirtualDevice> nics = getNicDevices(true);
+	    try {
+	        return nics.get(index);
+	    } catch (IndexOutOfBoundsException e) {
+	        // Not found
+	        return null;
+	    }
 	}
 
 	public Pair<Integer, VirtualDevice> getNicDeviceIndex(String networkNamePrefix) throws Exception {
-        List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().
-        getDynamicProperty(_mor, "config.hardware.device");
-
-        List<VirtualDevice> nics = new ArrayList<VirtualDevice>();
-        if(devices != null) {
-            for(VirtualDevice device : devices) {
-                if(device instanceof VirtualEthernetCard) {
-                    nics.add(device);
-                }
-            }
-        }
-
-        Collections.sort(nics, new Comparator<VirtualDevice>() {
-            @Override
-            public int compare(VirtualDevice arg0, VirtualDevice arg1) {
-                int unitNumber0 = arg0.getUnitNumber() != null ? arg0.getUnitNumber().intValue() : -1;
-                int unitNumber1 = arg1.getUnitNumber() != null ? arg1.getUnitNumber().intValue() : -1;
-                if(unitNumber0 < unitNumber1)
-                    return -1;
-                else if(unitNumber0 > unitNumber1)
-                    return 1;
-                return 0;
-            }
-        });
+        List<VirtualDevice> nics = getNicDevices(true);
 
         int index = 0;
         String attachedNetworkSummary;


[2/4] git commit: updated refs/heads/master to 2691970

Posted by hu...@apache.org.
Formatting changes using the settings from Alex


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/7dc3d3ba
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/7dc3d3ba
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/7dc3d3ba

Branch: refs/heads/master
Commit: 7dc3d3bae595782f03c414ec68bd9eb841bea29f
Parents: 392bbcc
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Thu Jul 11 10:25:26 2013 +0200
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Fri Jul 12 12:18:20 2013 +0200

----------------------------------------------------------------------
 .../vmware/manager/VmwareManagerImpl.java       | 16 ++--
 .../vmware/resource/VmwareResource.java         | 92 ++++----------------
 2 files changed, 27 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7dc3d3ba/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
index 9eb6d34..2f1ea68 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
@@ -36,8 +36,6 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 import org.apache.log4j.Logger;
 
 import com.google.gson.Gson;
@@ -45,10 +43,6 @@ import com.vmware.vim25.AboutInfo;
 import com.vmware.vim25.HostConnectSpec;
 import com.vmware.vim25.ManagedObjectReference;
 
-import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
-import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
-import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
-
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.Listener;
 import com.cloud.agent.api.AgentControlAnswer;
@@ -68,10 +62,10 @@ import com.cloud.dc.dao.ClusterDao;
 import com.cloud.dc.dao.ClusterVSMMapDao;
 import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.exception.DiscoveredWithErrorException;
-import com.cloud.host.Host;
 import com.cloud.exception.DiscoveryException;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.ResourceInUseException;
+import com.cloud.host.Host;
 import com.cloud.host.Status;
 import com.cloud.host.dao.HostDao;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -122,6 +116,12 @@ import com.cloud.utils.script.Script;
 import com.cloud.utils.ssh.SshHelper;
 import com.cloud.vm.DomainRouterVO;
 
+import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
+import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
+import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+
 
 @Local(value = {VmwareManager.class, VmwareDatacenterService.class})
 public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService {
@@ -459,7 +459,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
     @Override
     public String getSecondaryStorageStoreUrl(long dcId) {
 
-        DataStore secStore = this._dataStoreMgr.getImageStore(dcId);
+        DataStore secStore = _dataStoreMgr.getImageStore(dcId);
         if(secStore != null)
             return secStore.getUri();
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7dc3d3ba/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 57f3121..04978b5 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -48,9 +48,15 @@ import org.apache.log4j.NDC;
 
 import com.google.gson.Gson;
 import com.vmware.vim25.AboutInfo;
+import com.vmware.vim25.BoolPolicy;
 import com.vmware.vim25.ClusterDasConfigInfo;
 import com.vmware.vim25.ComputeResourceSummary;
+import com.vmware.vim25.DVPortConfigInfo;
+import com.vmware.vim25.DVPortConfigSpec;
 import com.vmware.vim25.DatastoreSummary;
+import com.vmware.vim25.DistributedVirtualPort;
+import com.vmware.vim25.DistributedVirtualSwitchPortConnection;
+import com.vmware.vim25.DistributedVirtualSwitchPortCriteria;
 import com.vmware.vim25.DynamicProperty;
 import com.vmware.vim25.GuestInfo;
 import com.vmware.vim25.HostCapability;
@@ -79,12 +85,15 @@ import com.vmware.vim25.PerfQuerySpec;
 import com.vmware.vim25.PerfSampleInfo;
 import com.vmware.vim25.RuntimeFaultFaultMsg;
 import com.vmware.vim25.ToolsUnavailableFaultMsg;
+import com.vmware.vim25.VMwareDVSPortSetting;
 import com.vmware.vim25.VimPortType;
 import com.vmware.vim25.VirtualDevice;
+import com.vmware.vim25.VirtualDeviceBackingInfo;
 import com.vmware.vim25.VirtualDeviceConfigSpec;
 import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
 import com.vmware.vim25.VirtualDisk;
 import com.vmware.vim25.VirtualEthernetCard;
+import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
 import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
 import com.vmware.vim25.VirtualLsiLogicController;
 import com.vmware.vim25.VirtualMachineConfigSpec;
@@ -95,12 +104,7 @@ import com.vmware.vim25.VirtualMachineRelocateSpec;
 import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
 import com.vmware.vim25.VirtualMachineRuntimeInfo;
 import com.vmware.vim25.VirtualSCSISharing;
-
-import org.apache.cloudstack.storage.command.DeleteCommand;
-import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
-import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
-import org.apache.cloudstack.storage.to.TemplateObjectTO;
-import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
 
 import com.cloud.agent.IAgentControl;
 import com.cloud.agent.api.Answer;
@@ -265,7 +269,6 @@ import com.cloud.hypervisor.vmware.mo.CustomFieldsManagerMO;
 import com.cloud.hypervisor.vmware.mo.DatacenterMO;
 import com.cloud.hypervisor.vmware.mo.DatastoreMO;
 import com.cloud.hypervisor.vmware.mo.DiskControllerType;
-import com.cloud.hypervisor.vmware.mo.DistributedVirtualSwitchMO;
 import com.cloud.hypervisor.vmware.mo.FeatureKeyConstants;
 import com.cloud.hypervisor.vmware.mo.HostDatastoreSystemMO;
 import com.cloud.hypervisor.vmware.mo.HostFirewallSystemMO;
@@ -320,68 +323,11 @@ import com.cloud.vm.VirtualMachine.State;
 import com.cloud.vm.VirtualMachineName;
 import com.cloud.vm.VmDetailConstants;
 
-import com.google.gson.Gson;
-import com.vmware.vim25.AboutInfo;
-import com.vmware.vim25.BoolPolicy;
-import com.vmware.vim25.ClusterDasConfigInfo;
-import com.vmware.vim25.ComputeResourceSummary;
-import com.vmware.vim25.DVPortConfigInfo;
-import com.vmware.vim25.DVPortConfigSpec;
-import com.vmware.vim25.DVPortSetting;
-import com.vmware.vim25.DatastoreSummary;
-import com.vmware.vim25.DistributedVirtualPort;
-import com.vmware.vim25.DistributedVirtualSwitchPortConnection;
-import com.vmware.vim25.DistributedVirtualSwitchPortCriteria;
-import com.vmware.vim25.DynamicProperty;
-import com.vmware.vim25.GuestInfo;
-import com.vmware.vim25.GuestOsDescriptor;
-import com.vmware.vim25.HostCapability;
-import com.vmware.vim25.HostFirewallInfo;
-import com.vmware.vim25.HostFirewallRuleset;
-import com.vmware.vim25.HostHostBusAdapter;
-import com.vmware.vim25.HostInternetScsiTargetTransport;
-import com.vmware.vim25.HostScsiTopology;
-import com.vmware.vim25.HostInternetScsiHba;
-import com.vmware.vim25.HostInternetScsiHbaAuthenticationProperties;
-import com.vmware.vim25.HostInternetScsiHbaStaticTarget;
-import com.vmware.vim25.HostScsiDisk;
-import com.vmware.vim25.HostScsiTopologyInterface;
-import com.vmware.vim25.HostScsiTopologyLun;
-import com.vmware.vim25.HostScsiTopologyTarget;
-import com.vmware.vim25.ManagedObjectReference;
-import com.vmware.vim25.ObjectContent;
-import com.vmware.vim25.OptionValue;
-import com.vmware.vim25.PerfCounterInfo;
-import com.vmware.vim25.PerfEntityMetric;
-import com.vmware.vim25.PerfEntityMetricBase;
-import com.vmware.vim25.PerfMetricId;
-import com.vmware.vim25.PerfMetricIntSeries;
-import com.vmware.vim25.PerfMetricSeries;
-import com.vmware.vim25.PerfQuerySpec;
-import com.vmware.vim25.PerfSampleInfo;
-import com.vmware.vim25.RuntimeFaultFaultMsg;
-import com.vmware.vim25.ToolsUnavailableFaultMsg;
-import com.vmware.vim25.VMwareDVSPortSetting;
-import com.vmware.vim25.VimPortType;
-import com.vmware.vim25.VirtualDevice;
-import com.vmware.vim25.VirtualDeviceBackingInfo;
-import com.vmware.vim25.VirtualDeviceConfigSpec;
-import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
-import com.vmware.vim25.VirtualDisk;
-import com.vmware.vim25.VirtualEthernetCard;
-import com.vmware.vim25.VirtualEthernetCardDistributedVirtualPortBackingInfo;
-import com.vmware.vim25.VirtualEthernetCardNetworkBackingInfo;
-import com.vmware.vim25.VirtualLsiLogicController;
-import com.vmware.vim25.VirtualMachineConfigOption;
-import com.vmware.vim25.VirtualMachineConfigSpec;
-import com.vmware.vim25.VirtualMachineFileInfo;
-import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
-import com.vmware.vim25.VirtualMachinePowerState;
-import com.vmware.vim25.VirtualMachineRelocateSpec;
-import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator;
-import com.vmware.vim25.VirtualMachineRuntimeInfo;
-import com.vmware.vim25.VirtualSCSISharing;
-import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
 
 
 public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService {
@@ -1559,7 +1505,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             s_logger.info("Executing resource PlugNicCommand " + _gson.toJson(cmd));
         }
 
-        VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+        getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
         VmwareContext context = getServiceContext();
         try {
             VmwareHypervisorHost hyperHost = getHyperHost(context);
@@ -2094,7 +2040,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         if (s_logger.isInfoEnabled()) {
             s_logger.info("Executing createIpAlias command: " + _gson.toJson(cmd));
         }
-        String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+        cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
         List<IpAliasTO> ipAliasTOs = cmd.getIpAliasList();
         String args="";
         for (IpAliasTO ipaliasto : ipAliasTOs) {
@@ -2130,7 +2076,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
     }
 
     protected Answer execute(final DeleteIpAliasCommand cmd) {
-        String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
+        cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
         List<IpAliasTO> revokedIpAliasTOs = cmd.getDeleteIpAliasTos();
         List<IpAliasTO> activeIpAliasTOs = cmd.getCreateIpAliasTos();
         if (s_logger.isInfoEnabled()) {
@@ -6264,7 +6210,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         String vmName = mgr.composeWorkerName();
 
         assert(cmd != null);
-        VmwareManager vmwareMgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+        context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
         // TODO: Fix this? long checkPointId = vmwareMgr.pushCleanupCheckpoint(this._guid, vmName);
         // TODO: Fix this? cmd.setContextParam("checkpoint", String.valueOf(checkPointId));
         return vmName;


[4/4] git commit: updated refs/heads/master to 2691970

Posted by hu...@apache.org.
CLOUDSTACK-728 Get the framework in place the support the removal of the portgroup that is created for a nic connected to an lswitch.

Add a command to tell a hypervisor guru to take some action when
expunging a nic


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/2691970f
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2691970f
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2691970f

Branch: refs/heads/master
Commit: 2691970f280c0d997f294510a7244a625151f3da
Parents: 7dc3d3b
Author: Hugo Trippaers <ht...@schubergphilis.com>
Authored: Wed Jul 10 17:48:33 2013 +0200
Committer: Hugo Trippaers <ht...@schubergphilis.com>
Committed: Fri Jul 12 12:18:34 2013 +0200

----------------------------------------------------------------------
 .../com/cloud/hypervisor/HypervisorGuru.java    |   9 +-
 .../cloud/agent/api/UnregisterNicCommand.java   |  55 +++
 .../com/cloud/hypervisor/guru/VMwareGuru.java   |  80 ++--
 .../vmware/resource/VmwareResource.java         | 379 +++++++++++--------
 .../cloud/hypervisor/HypervisorGuruBase.java    |  28 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 339 +++++++++--------
 6 files changed, 530 insertions(+), 360 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2691970f/api/src/com/cloud/hypervisor/HypervisorGuru.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/hypervisor/HypervisorGuru.java b/api/src/com/cloud/hypervisor/HypervisorGuru.java
index eab4e4e..47ca17a 100644
--- a/api/src/com/cloud/hypervisor/HypervisorGuru.java
+++ b/api/src/com/cloud/hypervisor/HypervisorGuru.java
@@ -59,11 +59,18 @@ public interface HypervisorGuru extends Adapter {
      * @return
      */
     NicTO toNicTO(NicProfile profile);
-    
+
     /**
      * Give hypervisor guru opportunity to decide if certain command needs to be done after expunge VM from DB
      * @param vm
      * @return a list of Commands
      */
     List<Command> finalizeExpunge(VirtualMachine vm);
+
+    /**
+     * Give the hypervisor guru the opportinity to decide if additional clean is
+     * required for nics before expunging the VM
+     * 
+     */
+    List<Command> finalizeExpungeNics(VirtualMachine vm, List<NicProfile> nics);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2691970f/core/src/com/cloud/agent/api/UnregisterNicCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/UnregisterNicCommand.java b/core/src/com/cloud/agent/api/UnregisterNicCommand.java
new file mode 100644
index 0000000..0256d64
--- /dev/null
+++ b/core/src/com/cloud/agent/api/UnregisterNicCommand.java
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api;
+
+import java.util.UUID;
+
+/**
+ * This command will tell the hypervisor to cleanup any resources dedicated for
+ * this particular nic. Orginally implemented to cleanup dedicated portgroups
+ * from a vmware standard switch
+ *
+ */
+public class UnregisterNicCommand extends Command {
+    private String vmName;
+    private String trafficLabel;
+    private UUID nicUuid;
+
+    public UnregisterNicCommand(String vmName, String trafficLabel, UUID nicUuid) {
+        this.nicUuid = nicUuid;
+        this.vmName = vmName;
+        this.trafficLabel = trafficLabel;
+    }
+
+    public UUID getNicUuid() {
+        return nicUuid;
+    }
+
+    public String getVmName() {
+        return vmName;
+    }
+
+    public String getTrafficLabel() {
+        return trafficLabel;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2691970f/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
index 95521e8..4c4d8df 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -12,7 +12,7 @@
 // Unless required by applicable law or agreed to in writing,
 // software distributed under the License is distributed on an
 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the 
+// KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
 package com.cloud.hypervisor.guru;
@@ -23,20 +23,19 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 
 import javax.ejb.Local;
 import javax.inject.Inject;
 
-import org.apache.cloudstack.api.ApiConstants.VMDetails;
-import org.apache.cloudstack.storage.command.CopyCommand;
 import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
 
 import com.cloud.agent.api.BackupSnapshotCommand;
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
 import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
 import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
+import com.cloud.agent.api.UnregisterNicCommand;
 import com.cloud.agent.api.UnregisterVMCommand;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
 import com.cloud.agent.api.storage.CreateVolumeOVACommand;
@@ -60,11 +59,15 @@ import com.cloud.hypervisor.HypervisorGuruBase;
 import com.cloud.hypervisor.vmware.manager.VmwareManager;
 import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
 import com.cloud.network.Network.Provider;
-import com.cloud.network.NetworkModel;
 import com.cloud.network.Network.Service;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.Networks.BroadcastDomainType;
 import com.cloud.network.Networks.TrafficType;
 import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
+import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
 import com.cloud.secstorage.CommandExecLogDao;
 import com.cloud.secstorage.CommandExecLogVO;
 import com.cloud.storage.DataStoreRole;
@@ -79,10 +82,14 @@ import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.ConsoleProxyVO;
 import com.cloud.vm.DomainRouterVO;
 import com.cloud.vm.NicProfile;
+import com.cloud.vm.NicVO;
 import com.cloud.vm.SecondaryStorageVmVO;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.VmDetailConstants;
+import com.cloud.vm.dao.NicDao;
+
+import org.apache.cloudstack.storage.command.CopyCommand;
 
 @Local(value=HypervisorGuru.class)
 public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
@@ -98,6 +105,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
     @Inject SecondaryStorageVmManager _secStorageMgr;
     @Inject NetworkModel _networkMgr;
     @Inject ConfigurationDao _configDao;
+    @Inject
+    NicDao _nicDao;
+    @Inject
+    PhysicalNetworkDao _physicalNetworkDao;
+    @Inject
+    PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao;
 
     protected VMwareGuru() {
         super();
@@ -118,7 +131,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
             details = new HashMap<String, String>();
 
         String nicDeviceType = details.get(VmDetailConstants.NIC_ADAPTER);
-        if(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO 
+        if(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO
                 || vm.getVirtualMachine() instanceof SecondaryStorageVmVO) {
 
             if(nicDeviceType == null) {
@@ -144,13 +157,13 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
                 }
             }
         }
-        
+
         String diskDeviceType = details.get(VmDetailConstants.ROOK_DISK_CONTROLLER);
-        if (!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO 
-            || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)){
+        if (!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO
+                || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)){
             // user vm
             if (diskDeviceType == null){
-		    details.put(VmDetailConstants.ROOK_DISK_CONTROLLER, _vmwareMgr.getRootDiskController());
+                details.put(VmDetailConstants.ROOK_DISK_CONTROLLER, _vmwareMgr.getRootDiskController());
             }
         }
 
@@ -236,19 +249,19 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
             sbMacSequence.deleteCharAt(sbMacSequence.length() - 1);
             String bootArgs = to.getBootArgs();
             to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString());
-            
+
         }
-        
+
         // Don't do this if the virtual machine is one of the special types
         // Should only be done on user machines
-        if(!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO 
+        if(!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO
                 || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)) {
             String nestedVirt = _configDao.getValue(Config.VmwareEnableNestedVirtualization.key());
             if (nestedVirt != null) {
                 s_logger.debug("Nested virtualization requested, adding flag to vm configuration");
                 details.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, nestedVirt);
                 to.setDetails(details);
-                
+
             }
         }
         // Determine the VM's OS description
@@ -284,7 +297,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
     public long getCommandHostDelegation(long hostId, Command cmd) {
         boolean needDelegation = false;
 
-        if(cmd instanceof PrimaryStorageDownloadCommand || 
+        if(cmd instanceof PrimaryStorageDownloadCommand ||
                 cmd instanceof BackupSnapshotCommand ||
                 cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
                 cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
@@ -299,7 +312,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
                 DataStoreTO srcStoreTO = srcData.getDataStore();
                 DataTO destData = cpyCommand.getDestTO();
                 DataStoreTO destStoreTO = destData.getDataStore();
-                
+
                 if (destData.getObjectType() == DataObjectType.VOLUME && destStoreTO.getRole() == DataStoreRole.Primary &&
                         srcData.getObjectType() == DataObjectType.TEMPLATE && srcStoreTO.getRole() == DataStoreRole.Primary) {
                     needDelegation = false;
@@ -309,14 +322,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
             } else {
                 needDelegation = true;
             }
-            
+
         }
         /* Fang: remove this before checking in */
         // needDelegation = false;
 
         if (cmd instanceof PrepareOVAPackingCommand ||
                 cmd instanceof CreateVolumeOVACommand	) {
-                cmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
+            cmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
         }
         if(needDelegation) {
             HostVO host = _hostDao.findById(hostId);
@@ -339,8 +352,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
                 _cmdExecLogDao.persist(execLog);
                 cmd.setContextParam("execid", String.valueOf(execLog.getId()));
 
-                if(cmd instanceof BackupSnapshotCommand || 
-                        cmd instanceof CreatePrivateTemplateFromVolumeCommand || 
+                if(cmd instanceof BackupSnapshotCommand ||
+                        cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
                         cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
                         cmd instanceof CopyVolumeCommand ||
                         cmd instanceof CreateVolumeOVACommand ||
@@ -349,14 +362,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
 
                     String workerName = _vmwareMgr.composeWorkerName();
                     long checkPointId = 1;
-// FIXME: Fix                    long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName));
+                    // FIXME: Fix                    long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName));
                     cmd.setContextParam("worker", workerName);
                     cmd.setContextParam("checkpoint", String.valueOf(checkPointId));
 
                     // some commands use 2 workers
                     String workerName2 = _vmwareMgr.composeWorkerName();
                     long checkPointId2 = 1;
-// FIXME: Fix                    long checkPointId2 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2));
+                    // FIXME: Fix                    long checkPointId2 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2));
                     cmd.setContextParam("worker2", workerName2);
                     cmd.setContextParam("checkpoint2", String.valueOf(checkPointId2));
                 }
@@ -388,7 +401,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
 
         return tokens[0] + "@" + vCenterIp;
     }
-    
+
     @Override
     public List<Command> finalizeExpunge(VirtualMachine vm) {
         UnregisterVMCommand unregisterVMCommand = new UnregisterVMCommand(vm.getInstanceName());
@@ -396,4 +409,25 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
         commands.add(unregisterVMCommand);
         return commands;
     }
+
+    @Override
+    public List<Command> finalizeExpungeNics(VirtualMachine vm, List<NicProfile> nics) {
+        List<Command> commands = new ArrayList<Command>();
+        List<NicVO> nicVOs = _nicDao.listByVmId(vm.getId());
+        for (NicVO nic : nicVOs) {
+            NetworkVO network = _networkDao.findById(nic.getNetworkId());
+            if (network.getBroadcastDomainType() == BroadcastDomainType.Lswitch) {
+                s_logger.debug("Nic " + nic.toString() + " is connected to an lswitch, cleanup required");
+                NetworkVO networkVO = _networkDao.findById(nic.getNetworkId());
+                // We need the traffic label to figure out which vSwitch has the
+                // portgroup
+                PhysicalNetworkTrafficTypeVO trafficTypeVO = _physicalNetworkTrafficTypeDao.findBy(
+                        networkVO.getPhysicalNetworkId(), networkVO.getTrafficType());
+                UnregisterNicCommand unregisterNicCommand = new UnregisterNicCommand(vm.getInstanceName(),
+                        trafficTypeVO.getVmwareNetworkLabel(), UUID.fromString(nic.getUuid()));
+                commands.add(unregisterNicCommand);
+            }
+        }
+        return commands;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2691970f/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 04978b5..3573500 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -193,6 +193,7 @@ import com.cloud.agent.api.StopCommand;
 import com.cloud.agent.api.StoragePoolInfo;
 import com.cloud.agent.api.UnPlugNicAnswer;
 import com.cloud.agent.api.UnPlugNicCommand;
+import com.cloud.agent.api.UnregisterNicCommand;
 import com.cloud.agent.api.UnregisterVMCommand;
 import com.cloud.agent.api.UpgradeSnapshotCommand;
 import com.cloud.agent.api.ValidateSnapshotAnswer;
@@ -391,7 +392,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
     }
 
     public Gson getGson() {
-    	return _gson;
+        return _gson;
     }
 
     public VmwareResource() {
@@ -545,12 +546,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             } else if (clz == SetNetworkACLCommand.class) {
                 answer = execute((SetNetworkACLCommand) cmd);
             } else if (cmd instanceof CreateVMSnapshotCommand) {
-            	return execute((CreateVMSnapshotCommand)cmd);
+                return execute((CreateVMSnapshotCommand)cmd);
             } else if(cmd instanceof DeleteVMSnapshotCommand){
-            	return execute((DeleteVMSnapshotCommand)cmd);
+                return execute((DeleteVMSnapshotCommand)cmd);
             } else if(cmd instanceof RevertToVMSnapshotCommand){
-            	return execute((RevertToVMSnapshotCommand)cmd);
-        	}else if (clz == SetPortForwardingRulesVpcCommand.class) {
+                return execute((RevertToVMSnapshotCommand)cmd);
+            }else if (clz == SetPortForwardingRulesVpcCommand.class) {
                 answer = execute((SetPortForwardingRulesVpcCommand) cmd);
             } else if (clz == Site2SiteVpnCfgCommand.class) {
                 answer = execute((Site2SiteVpnCfgCommand) cmd);
@@ -561,13 +562,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             } else if (clz == UnregisterVMCommand.class) {
                 return execute((UnregisterVMCommand) cmd);
             } else if (cmd instanceof StorageSubSystemCommand) {
-            	return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
+                return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
             } else if (clz == ScaleVmCommand.class) {
                 return execute((ScaleVmCommand) cmd);
             } else if (clz == PvlanSetupCommand.class) {
                 return execute((PvlanSetupCommand) cmd);
             } else if (clz == SetStaticRouteCommand.class) {
                 answer = execute((SetStaticRouteCommand) cmd);
+            } else if (clz == UnregisterNicCommand.class) {
+                answer = execute((UnregisterNicCommand) cmd);
             } else {
                 answer = Answer.createUnsupportedCommandAnswer(cmd);
             }
@@ -873,8 +876,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                         null, "/root/firewallRule_egress.sh " + args);
             } else {
                 result = SshHelper.sshExecute(controlIp,
-                    DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(),
-                    null, "/root/firewall_rule.sh " + args);
+                        DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(),
+                        null, "/root/firewall_rule.sh " + args);
             }
 
             if (s_logger.isDebugEnabled()) {
@@ -882,10 +885,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                     s_logger.debug("Executing script on domain router " + controlIp
                             + ": /root/firewallRule_egress.sh " + args);
                 } else {
-                s_logger.debug("Executing script on domain router " + controlIp
-                        + ": /root/firewall_rule.sh " + args);
-                 }
-             }
+                    s_logger.debug("Executing script on domain router " + controlIp
+                            + ": /root/firewall_rule.sh " + args);
+                }
+            }
 
 
             if (!result.first()) {
@@ -1126,21 +1129,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         return -1;
     }
 
-//
-// find mac address of a specified ethx device
-//    ip address show ethx | grep link/ether | sed -e 's/^[ \t]*//' | cut -d' ' -f2
-// returns
-//      eth0:xx.xx.xx.xx
+    //
+    // find mac address of a specified ethx device
+    //    ip address show ethx | grep link/ether | sed -e 's/^[ \t]*//' | cut -d' ' -f2
+    // returns
+    //      eth0:xx.xx.xx.xx
 
-//
-// list IP with eth devices
-//  ifconfig ethx |grep -B1 "inet addr" | awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }'
-//     | awk -F: '{ print $1 ": " $3 }'
-//
-// returns
-//      eth0:xx.xx.xx.xx
-//
-//
+    //
+    // list IP with eth devices
+    //  ifconfig ethx |grep -B1 "inet addr" | awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }'
+    //     | awk -F: '{ print $1 ": " $3 }'
+    //
+    // returns
+    //      eth0:xx.xx.xx.xx
+    //
+    //
     private int findRouterEthDeviceIndex(String domrName, String routerIp, String mac) throws Exception {
         VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
 
@@ -1982,7 +1985,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
         String args = " -m " + cmd.getVmMac();
         if (cmd.getVmIpAddress() != null) {
-        	args += " -4 " + cmd.getVmIpAddress();
+            args += " -4 " + cmd.getVmIpAddress();
         }
         args += " -h " + cmd.getVmName();
 
@@ -1999,12 +2002,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         }
 
         if (cmd.getVmIp6Address() != null) {
-        	args += " -6 " + cmd.getVmIp6Address();
-        	args += " -u " + cmd.getDuid();
+            args += " -6 " + cmd.getVmIp6Address();
+            args += " -u " + cmd.getDuid();
         }
 
         if (!cmd.isDefault()) {
-        	args += " -N";
+            args += " -N";
         }
 
         if (s_logger.isDebugEnabled()) {
@@ -2413,16 +2416,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
         for (DiskTO vol : disks) {
             if (vol.getType() != Volume.Type.ISO) {
-            	VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
-            	PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
-            	if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) {
-            		validatedDisks.add(vol);
-            	}
+                VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
+                PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+                if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) {
+                    validatedDisks.add(vol);
+                }
             } else if (vol.getType() == Volume.Type.ISO) {
-            	TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData();
-            	if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) {
-            		validatedDisks.add(vol);
-            	}
+                TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData();
+                if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) {
+                    validatedDisks.add(vol);
+                }
             } else {
                 if (s_logger.isDebugEnabled()) {
                     s_logger.debug("Drop invalid disk option, volumeTO: " + _gson.toJson(vol));
@@ -2468,7 +2471,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             // Check if license supports the feature
             VmwareHelper.isFeatureLicensed(hyperHost, FeatureKeyConstants.HOTPLUG);
             VmwareHelper
-                    .setVmScaleUpConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(), (int)requestedMaxMemoryInMb, ramMb, vmSpec.getLimitCpuUse());
+            .setVmScaleUpConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(), (int)requestedMaxMemoryInMb, ramMb, vmSpec.getLimitCpuUse());
 
             if(!vmMo.configureVm(vmConfigSpec)) {
                 throw new Exception("Unable to execute ScaleVmCommand");
@@ -2543,15 +2546,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                     Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
                     for (DiskTO vol : disks) {
                         if (vol.getType() == Volume.Type.ROOT) {
-                        	PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore();
+                            PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore();
                             rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
                         }
                     }
 
                     assert (vmSpec.getMinSpeed() != null) && (rootDiskDataStoreDetails != null);
                     if (!hyperHost.createBlankVm(vmName, vmSpec.getCpus(), vmSpec.getMaxSpeed().intValue(),
-                    vmSpec.getMinSpeed(), vmSpec.getLimitCpuUse(),(int)(vmSpec.getMaxRam()/(1024*1024)), ramMb,
-                    translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), rootDiskDataStoreDetails.first(), false)) {
+                            vmSpec.getMinSpeed(), vmSpec.getLimitCpuUse(),(int)(vmSpec.getMaxRam()/(1024*1024)), ramMb,
+                            translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), rootDiskDataStoreDetails.first(), false)) {
                         throw new Exception("Failed to create VM. vmName: " + vmName);
                     }
                 }
@@ -2582,8 +2585,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
             int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024));
             VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(),
-            vmSpec.getMinSpeed(),(int) (vmSpec.getMaxRam()/(1024*1024)), ramMb,
-            translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), vmSpec.getLimitCpuUse());
+                    vmSpec.getMinSpeed(),(int) (vmSpec.getMaxRam()/(1024*1024)), ramMb,
+                    translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), vmSpec.getLimitCpuUse());
             String guestOsId = translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value();
             // Check for hotadd settings
             vmConfigSpec.setMemoryHotAddEnabled(vmMo.isMemoryHotAddSupported(guestOsId));
@@ -2601,8 +2604,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                     vmConfigSpec.setNestedHVEnabled(true);
                 }
                 else {
-                	s_logger.warn("Hypervisor doesn't support nested virtualization, unable to set config for VM " +vmSpec.getName());
-                	vmConfigSpec.setNestedHVEnabled(false);
+                    s_logger.warn("Hypervisor doesn't support nested virtualization, unable to set config for VM " +vmSpec.getName());
+                    vmConfigSpec.setNestedHVEnabled(false);
                 }
             }
 
@@ -2650,33 +2653,33 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 // we will always plugin a CDROM device
 
                 if (volIso != null) {
-                	TemplateObjectTO iso = (TemplateObjectTO)volIso.getData();
-
-                	if (iso.getPath() != null && !iso.getPath().isEmpty()) {
-                		DataStoreTO imageStore = iso.getDataStore();
-                		if (!(imageStore instanceof NfsTO)) {
-                			s_logger.debug("unsupported protocol");
-                			throw new Exception("unsupported protocol");
-                		}
-                		NfsTO nfsImageStore = (NfsTO)imageStore;
-                		String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
-                		Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath);
-                		assert (isoDatastoreInfo != null);
-                		assert (isoDatastoreInfo.second() != null);
-
-                		deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
-                    Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber++, i + 1);
-                		deviceConfigSpecArray[i].setDevice(isoInfo.first());
-                		if (isoInfo.second()) {
-                			if(s_logger.isDebugEnabled())
-                				s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
-                			deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
-                		} else {
-                			if(s_logger.isDebugEnabled())
-                				s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
-                			deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
-                		}
-                	}
+                    TemplateObjectTO iso = (TemplateObjectTO)volIso.getData();
+
+                    if (iso.getPath() != null && !iso.getPath().isEmpty()) {
+                        DataStoreTO imageStore = iso.getDataStore();
+                        if (!(imageStore instanceof NfsTO)) {
+                            s_logger.debug("unsupported protocol");
+                            throw new Exception("unsupported protocol");
+                        }
+                        NfsTO nfsImageStore = (NfsTO)imageStore;
+                        String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
+                        Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath);
+                        assert (isoDatastoreInfo != null);
+                        assert (isoDatastoreInfo.second() != null);
+
+                        deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
+                        Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber++, i + 1);
+                        deviceConfigSpecArray[i].setDevice(isoInfo.first());
+                        if (isoInfo.second()) {
+                            if(s_logger.isDebugEnabled())
+                                s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
+                            deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
+                        } else {
+                            if(s_logger.isDebugEnabled())
+                                s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
+                            deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
+                        }
+                    }
                 } else {
                     deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
                     Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, ideUnitNumber++, i + 1);
@@ -2718,8 +2721,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 }
 
                 if (vol.getType() != Volume.Type.ISO) {
-                	VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
-                	PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+                    VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
+                    PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
                     Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid());
                     assert (volumeDsDetails != null);
                     VirtualDevice device;
@@ -2731,7 +2734,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                         if (diskChain == null || diskChain.length < 1) {
                             s_logger.warn("Empty previously-saved chain info, fall back to the original");
                             device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(),
-                            		(controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1);
+                                    (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1);
                         } else {
                             s_logger.info("Attach the disk with stored chain info: " + chainInfo);
                             for (int j = 0; j < diskChain.length; j++) {
@@ -2739,11 +2742,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                             }
 
                             device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, diskChain, volumeDsDetails.first(),
-                            		(controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1);
+                                    (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1);
                         }
                     } else {
                         device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(),
-                        		(controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1);
+                                (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1);
                     }
                     deviceConfigSpecArray[i].setDevice(device);
                     deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
@@ -2807,7 +2810,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             newVal.setKey("devices.hotplug");
             newVal.setValue("true");
             extraOptions.add(newVal);
-            
+
             /**
              * Extra Config : nvp.vm-uuid = uuid
              *  - Required for Nicira NVP integration
@@ -2816,7 +2819,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             newVal.setKey("nvp.vm-uuid");
             newVal.setValue(vmSpec.getUuid());
             extraOptions.add(newVal);
-            
+
             /**
              * Extra Config : nvp.iface-id.<num> = uuid
              *  - Required for Nicira NVP integration
@@ -2829,7 +2832,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 extraOptions.add(newVal);
                 nicNum++;
             }
-            
+
             for(Map.Entry<String, String> entry : validateVmDetails(vmSpec.getDetails()).entrySet()) {
                 newVal = new OptionValue();
                 newVal.setKey(entry.getKey());
@@ -2848,49 +2851,71 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
             vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMask));
 
+            /**
+             * We need to configure the port on the DV switch after the host is
+             * connected. So make this happen between the configure and start of
+             * the VM
+             */
             int nicIndex = 0;
             for (NicTO nicTo : sortNicsByDeviceId(nics)) {
-                s_logger.debug("Checking for port configuration on NIC device : " + nicTo.toString());
                 if (nicTo.getBroadcastType() == BroadcastDomainType.Lswitch) {
                     // We need to create a port with a unique vlan and pass the key to the nic device
-                    s_logger.debug("Nic " + nicTo.toString() + " needs to be configured for NVP");
+                    s_logger.trace("Nic " + nicTo.toString() + " is connected to an NVP logicalswitch");
                     VirtualDevice nicVirtualDevice = vmMo.getNicDeviceByIndex(nicIndex);
                     if (nicVirtualDevice == null) {
                         throw new Exception("Failed to find a VirtualDevice for nic " + nicIndex); //FIXME Generic exceptions are bad
                     }
                     VirtualDeviceBackingInfo backing = nicVirtualDevice.getBacking();
                     if (backing instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo) {
+                        // This NIC is connected to a Distributed Virtual Switch
                         VirtualEthernetCardDistributedVirtualPortBackingInfo portInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo) backing;
                         DistributedVirtualSwitchPortConnection port = portInfo.getPort();
                         String portKey = port.getPortKey();
                         String portGroupKey = port.getPortgroupKey();
                         String dvSwitchUuid = port.getSwitchUuid();
-                        
+
                         s_logger.debug("NIC " + nicTo.toString() + " is connected to dvSwitch " + dvSwitchUuid + " pg " + portGroupKey + " port " + portKey);
-                        
+
                         ManagedObjectReference dvSwitchManager = vmMo.getContext().getVimClient().getServiceContent().getDvSwitchManager();
                         ManagedObjectReference dvSwitch = vmMo.getContext().getVimClient().getService().queryDvsByUuid(dvSwitchManager, dvSwitchUuid);
-                        
+
+                        // Get all ports
                         DistributedVirtualSwitchPortCriteria criteria = new DistributedVirtualSwitchPortCriteria();
                         criteria.setInside(true);
                         criteria.getPortgroupKey().add(portGroupKey);
-                        criteria.getPortKey().add(portKey);
                         List<DistributedVirtualPort> dvPorts = vmMo.getContext().getVimClient().getService().fetchDVPorts(dvSwitch, criteria);
-                        
-                        if (dvPorts.isEmpty()) {
+
+                        DistributedVirtualPort vmDvPort = null;
+                        List<Integer> usedVlans = new ArrayList<Integer>();
+                        for (DistributedVirtualPort dvPort : dvPorts) {
+                            // Find the port for this NIC by portkey
+                            if (portKey.equals(dvPort.getKey())) {
+                                vmDvPort = dvPort;
+                            }
+                            VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPort
+                                    .getConfig().getSetting();
+                            VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings
+                                    .getVlan();
+                            s_logger.trace("Found port " + dvPort.getKey()
+                                    + " with vlan " + vlanId.getVlanId());
+                            if (vlanId.getVlanId() > 0
+                                    && vlanId.getVlanId() < 4095) {
+                                usedVlans.add(vlanId.getVlanId());
+                            }
+                        }
+
+                        if (vmDvPort == null) {
                             throw new Exception("Empty port list from dvSwitch for nic " + nicTo.toString());
-                        } else if (dvPorts.size() > 1) {
-                            throw new Exception("Expected only one port in the list from dvSwitch for nic " + nicTo.toString());
                         }
 
-                        DistributedVirtualPort dvPort = dvPorts.get(0);
-                        DVPortConfigInfo dvPortConfigInfo = dvPort.getConfig();
+                        DVPortConfigInfo dvPortConfigInfo = vmDvPort
+                                .getConfig();
                         VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPortConfigInfo.getSetting();
-                        
+
                         VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan();
                         BoolPolicy blocked = settings.getBlocked();
                         if (blocked.isValue() == Boolean.TRUE) {
-                            s_logger.debug("Port is blocked, we need to set a vlanid and unblock"); 
+                            s_logger.trace("Port is blocked, set a vlanid and unblock");
                             DVPortConfigSpec dvPortConfigSpec = new DVPortConfigSpec();
                             VMwareDVSPortSetting edittedSettings = new VMwareDVSPortSetting();
                             // Unblock
@@ -2898,10 +2923,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                             blocked.setInherited(Boolean.FALSE);
                             edittedSettings.setBlocked(blocked);
                             // Set vlan
-                            vlanId.setVlanId(100); //FIXME should be a determined based on usage
+                            for (i = 1; i < 4095; i++) {
+                                if (!usedVlans.contains(i))
+                                    break;
+                            }
+                            vlanId.setVlanId(i); // FIXME should be a determined
+                            // based on usage
                             vlanId.setInherited(false);
                             edittedSettings.setVlan(vlanId);
-                            
+
                             dvPortConfigSpec.setSetting(edittedSettings);
                             dvPortConfigSpec.setOperation("edit");
                             dvPortConfigSpec.setKey(portKey);
@@ -2909,11 +2939,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                             dvPortConfigSpecs.add(dvPortConfigSpec);
                             ManagedObjectReference task = vmMo.getContext().getVimClient().getService().reconfigureDVPortTask(dvSwitch, dvPortConfigSpecs);
                             if (!vmMo.getContext().getVimClient().waitForTask(task)) {
-                                s_logger.error("Failed to configure the dvSwitch port for nic " + nicTo.toString());
+                                throw new Exception(
+                                        "Failed to configure the dvSwitch port for nic "
+                                                + nicTo.toString());
                             }
+                            s_logger.debug("NIC " + nicTo.toString()
+                                    + " connected to vlan " + i);
                         } else {
                             s_logger.trace("Port already configured and set to vlan " + vlanId.getVlanId());
                         }
+                    } else if (backing instanceof VirtualEthernetCardNetworkBackingInfo) {
+                        // This NIC is connected to a Virtual Switch
+                        // Nothing to do
                     }
                     else {
                         s_logger.error("nic device backing is of type " + backing.getClass().getName());
@@ -2926,8 +2963,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             if (!vmMo.powerOn()) {
                 throw new Exception("Failed to start VM. vmName: " + vmName);
             }
-            
-
 
             state = State.Running;
             return new StartAnswer(cmd);
@@ -3030,8 +3065,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         assert (hyperHost != null) && (context != null);
         for (DiskTO vol : disks) {
             if (vol.getType() != Volume.Type.ISO) {
-            	VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
-            	PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+                VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
+                PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
                 String poolUuid = primaryStore.getUuid();
                 if(poolMors.get(poolUuid) == null) {
                     ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid);
@@ -3063,7 +3098,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             if (nicTo.getBroadcastUri() != null) {
                 if (nicTo.getBroadcastType() == BroadcastDomainType.Vlan)
                     // For vlan, the broadcast uri is of the form vlan://<vlanid>
-                return nicTo.getBroadcastUri().getHost();
+                    return nicTo.getBroadcastUri().getHost();
                 else
                     // for pvlan, the broacast uri will be of the form pvlan://<vlanid>-i<pvlanid>
                     return NetUtils.getPrimaryPvlanFromUri(nicTo.getBroadcastUri());
@@ -3120,7 +3155,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 svlanId = getPvlanInfo(nicTo);
             }
             networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, vlanId, svlanId,
-                    nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, switchType, 
+                    nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, switchType,
                     _portsPerDvPortGroup, nicTo.getGateway(), configureVServiceInNexus, nicTo.getBroadcastType());
         }
 
@@ -4038,9 +4073,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
         if (cmd.getAttach()) {
             morDs = createVmfsDatastore(hyperHost, iqn,
-                        cmd.getStorageHost(), cmd.getStoragePort(), iqn,
-                        cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(),
-                        cmd.getChapTargetUsername(), cmd.getChapTargetPassword());
+                    cmd.getStorageHost(), cmd.getStoragePort(), iqn,
+                    cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(),
+                    cmd.getChapTargetUsername(), cmd.getChapTargetPassword());
 
             DatastoreMO dsMo = new DatastoreMO(context, morDs);
 
@@ -4056,15 +4091,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 }
 
                 vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dsMo.getSummary().getFreeSpace()),
-                		morDs, vmMo.getScsiDeviceControllerKey());
+                        morDs, vmMo.getScsiDeviceControllerKey());
                 vmMo.detachDisk(volumeDatastorePath, false);
-        	}
+            }
         }
         else {
-        	deleteVmfsDatastore(hyperHost, iqn, cmd.getStorageHost(), cmd.getStoragePort(), iqn);
+            deleteVmfsDatastore(hyperHost, iqn, cmd.getStorageHost(), cmd.getStoragePort(), iqn);
         }
 
-    	return morDs;
+        return morDs;
     }
 
     protected Answer execute(AttachVolumeCommand cmd) {
@@ -4089,10 +4124,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             ManagedObjectReference morDs = null;
 
             if (cmd.getAttach() && cmd.isManaged()) {
-            	morDs = handleDatastoreAndVmdk(cmd);
+                morDs = handleDatastoreAndVmdk(cmd);
             }
             else {
-            	morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getPoolUuid());
+                morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getPoolUuid());
             }
 
             if (morDs == null) {
@@ -4115,7 +4150,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                 vmMo.detachDisk(datastoreVolumePath, false);
 
                 if (cmd.isManaged()) {
-                	handleDatastoreAndVmdk(cmd);
+                    handleDatastoreAndVmdk(cmd);
                 }
             }
 
@@ -4515,14 +4550,14 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
     }
 
     protected Answer execute(RevertToVMSnapshotCommand cmd){
-    	try{
-    		VmwareContext context = getServiceContext();
-			VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
-			return mgr.getStorageManager().execute(this, cmd);
-    	}catch (Exception e){
-    		e.printStackTrace();
-    		return new RevertToVMSnapshotAnswer(cmd,false,"");
-    	}
+        try{
+            VmwareContext context = getServiceContext();
+            VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+            return mgr.getStorageManager().execute(this, cmd);
+        }catch (Exception e){
+            e.printStackTrace();
+            return new RevertToVMSnapshotAnswer(cmd,false,"");
+        }
     }
     protected Answer execute(CreateVolumeFromSnapshotCommand cmd) {
         if (s_logger.isInfoEnabled()) {
@@ -4814,6 +4849,36 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         }
     }
 
+    /**
+     * UnregisterNicCommand is used to remove a portgroup created for this
+     * specific nic. The portgroup will have the name set to the UUID of the
+     * nic. Introduced to cleanup the portgroups created for each nic that is
+     * plugged into an lswitch (Nicira NVP plugin)
+     *
+     * @param cmd
+     * @return
+     */
+    protected Answer execute(UnregisterNicCommand cmd) {
+        if (s_logger.isInfoEnabled()) {
+            s_logger.info("Executing resource UnregisterNicCommand: " + _gson.toJson(cmd));
+        }
+
+        VmwareContext context = getServiceContext();
+        getHyperHost(context);
+        try {
+            return new Answer(cmd, true, "Not implemented yet");
+        } catch (Exception e) {
+            if (e instanceof RemoteException) {
+                s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+                invalidateServiceContext();
+            }
+
+            String msg = "UnregisterVMCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+            s_logger.error(msg);
+            return new Answer(cmd, false, msg);
+        }
+    }
+
     public Answer execute(DeleteCommand cmd) {
         if (s_logger.isInfoEnabled()) {
             s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
@@ -4889,9 +4954,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                         dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
                     } else {
                         if (s_logger.isInfoEnabled()) {
-                        s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk");
+                            s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk");
                         }
-                    dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true);
+                        dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true);
                     }
                     return new Answer(cmd, true, "Success");
                 }
@@ -6051,10 +6116,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(context, context.getServiceContent().getCustomFieldsManager());
             cfmMo.ensureCustomFieldDef("Datastore", CustomFieldConstants.CLOUD_UUID);
             if (_publicTrafficInfo != null && _publicTrafficInfo.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch ||
-                _guestTrafficInfo != null && _guestTrafficInfo.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch) {
+                    _guestTrafficInfo != null && _guestTrafficInfo.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch) {
                 cfmMo.ensureCustomFieldDef("DistributedVirtualPortgroup", CustomFieldConstants.CLOUD_GC_DVP);
             }
-                cfmMo.ensureCustomFieldDef("Network", CustomFieldConstants.CLOUD_GC);
+            cfmMo.ensureCustomFieldDef("Network", CustomFieldConstants.CLOUD_GC);
             cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_UUID);
             cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_NIC_MASK);
 
@@ -6063,7 +6128,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
             Map<String, String> vsmCredentials;
             if (_guestTrafficInfo.getVirtualSwitchType() == VirtualSwitchType.NexusDistributedVirtualSwitch ||
-                _publicTrafficInfo.getVirtualSwitchType() == VirtualSwitchType.NexusDistributedVirtualSwitch) {
+                    _publicTrafficInfo.getVirtualSwitchType() == VirtualSwitchType.NexusDistributedVirtualSwitch) {
                 vsmCredentials = mgr.getNexusVSMCredentialsByClusterId(Long.parseLong(_cluster));
                 if (vsmCredentials != null) {
                     s_logger.info("Stocking credentials while configuring resource.");
@@ -6118,8 +6183,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         int timeout = NumbersUtil.parseInt(value, 1440) * 1000;
         VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
         VmwareStorageProcessor storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, _fullCloneFlag, (VmwareStorageMount)mgr,
-        		timeout, this, _shutdown_waitMs
-        		);
+                timeout, this, _shutdown_waitMs
+                );
         storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor);
 
         return true;
@@ -6216,41 +6281,41 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         return vmName;
     }
 
-	@Override
-	public void setName(String name) {
-		// TODO Auto-generated method stub
+    @Override
+    public void setName(String name) {
+        // TODO Auto-generated method stub
 
-	}
+    }
 
-	@Override
-	public void setConfigParams(Map<String, Object> params) {
-		// TODO Auto-generated method stub
+    @Override
+    public void setConfigParams(Map<String, Object> params) {
+        // TODO Auto-generated method stub
 
-	}
+    }
 
-	@Override
-	public Map<String, Object> getConfigParams() {
-		// TODO Auto-generated method stub
-		return null;
-	}
+    @Override
+    public Map<String, Object> getConfigParams() {
+        // TODO Auto-generated method stub
+        return null;
+    }
 
-	@Override
-	public int getRunLevel() {
-		// TODO Auto-generated method stub
-		return 0;
-	}
+    @Override
+    public int getRunLevel() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
 
-	@Override
-	public void setRunLevel(int level) {
-		// TODO Auto-generated method stub
+    @Override
+    public void setRunLevel(int level) {
+        // TODO Auto-generated method stub
 
-	}
+    }
 
-	@Override
-	public Answer execute(DestroyCommand cmd) {
-		// TODO Auto-generated method stub
-		return null;
-	}
+    @Override
+    public Answer execute(DestroyCommand cmd) {
+        // TODO Auto-generated method stub
+        return null;
+    }
     private boolean isVMWareToolsInstalled(VirtualMachineMO vmMo) throws Exception{
         GuestInfo guestInfo = vmMo.getVmGuestInfo();
         return (guestInfo != null && guestInfo.getGuestState() != null && guestInfo.getGuestState().equalsIgnoreCase("running"));

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2691970f/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index 50bfb30..769648a 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -5,7 +5,7 @@
 // to you under the Apache License, Version 2.0 (the
 // "License"); you may not use this file except in compliance
 // with the License.  You may obtain a copy of the License at
-// 
+//
 //   http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing,
@@ -22,17 +22,13 @@ import java.util.Map;
 import javax.inject.Inject;
 
 import com.cloud.agent.api.Command;
-import com.cloud.agent.api.to.DataTO;
 import com.cloud.agent.api.to.DiskTO;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
-import com.cloud.agent.api.to.VolumeTO;
 import com.cloud.configuration.Config;
 import com.cloud.offering.ServiceOffering;
 import com.cloud.server.ConfigurationServer;
 import com.cloud.storage.dao.VMTemplateDetailsDao;
-import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.VMTemplateVO;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.NicVO;
@@ -41,12 +37,11 @@ import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.NicDao;
 import com.cloud.vm.dao.NicSecondaryIpDao;
-import com.cloud.vm.dao.UserVmDetailsDao;
 import com.cloud.vm.dao.VMInstanceDao;
 
 public abstract class HypervisorGuruBase extends AdapterBase implements HypervisorGuru {
-	
-	@Inject VMTemplateDetailsDao _templateDetailsDao;
+
+    @Inject VMTemplateDetailsDao _templateDetailsDao;
     @Inject NicDao _nicDao;
     @Inject VMInstanceDao _virtualMachineDao;
     @Inject NicSecondaryIpDao _nicSecIpDao;
@@ -74,7 +69,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
         to.setNetworkRateMbps(profile.getNetworkRate());
         to.setName(profile.getName());
         to.setSecurityGroupEnabled(profile.isSecurityGroupEnabled());
-        
+
         // Workaround to make sure the TO has the UUID we need for Niciri integration
         NicVO nicVO = _nicDao.findById(profile.getId());
         to.setUuid(nicVO.getUuid());
@@ -92,7 +87,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
 
     protected <T extends VirtualMachine> VirtualMachineTO  toVirtualMachineTO(VirtualMachineProfile<T> vmProfile) {
 
-        ServiceOffering offering = vmProfile.getServiceOffering();  
+        ServiceOffering offering = vmProfile.getServiceOffering();
         VirtualMachine vm = vmProfile.getVirtualMachine();
         Long minMemory = (long) (offering.getRamSize() / vmProfile.getMemoryOvercommitRatio());
         int minspeed = (int) (offering.getSpeed() / vmProfile.getCpuOvercommitRatio());
@@ -116,13 +111,13 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
         } else {
             to.setArch("x86_64");
         }
-        
+
         long templateId = vm.getTemplateId();
         Map<String, String> details = _templateDetailsDao.findDetails(templateId);
         assert(details != null);
         Map<String, String> detailsInVm = vm.getDetails();
         if(detailsInVm != null) {
-        	details.putAll(detailsInVm);
+            details.putAll(detailsInVm);
         }
         if (details.get(VirtualMachine.IsDynamicScalingEnabled) == null || details.get(VirtualMachine.IsDynamicScalingEnabled).isEmpty()) {
             to. setEnableDynamicallyScaleVm(false);
@@ -134,7 +129,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
         // Workaround to make sure the TO has the UUID we need for Niciri integration
         VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId());
         to.setUuid(vmInstance.getUuid());
-        
+
         //
         return to;
     }
@@ -143,9 +138,14 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
     public long getCommandHostDelegation(long hostId, Command cmd) {
         return hostId;
     }
-    
+
     @Override
     public List<Command> finalizeExpunge(VirtualMachine vm) {
         return null;
     }
+
+    @Override
+    public List<Command> finalizeExpungeNics(VirtualMachine vm, List<NicProfile> nics) {
+        return null;
+    }
 }


[3/4] CLOUDSTACK-728 Get the framework in place the support the removal of the portgroup that is created for a nic connected to an lswitch.

Posted by hu...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2691970f/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index cddd32e..827e233 100755
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -36,12 +36,6 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
-import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
-import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
-import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
-import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 import org.apache.log4j.Logger;
 
 import com.cloud.agent.AgentManager;
@@ -168,7 +162,6 @@ import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.exception.ExecutionException;
 import com.cloud.utils.fsm.NoTransitionException;
 import com.cloud.utils.fsm.StateMachine2;
-import com.cloud.vm.UserVmDetailVO;
 import com.cloud.vm.ItWorkVO.Step;
 import com.cloud.vm.VirtualMachine.Event;
 import com.cloud.vm.VirtualMachine.State;
@@ -181,6 +174,13 @@ import com.cloud.vm.snapshot.VMSnapshotManager;
 import com.cloud.vm.snapshot.VMSnapshotVO;
 import com.cloud.vm.snapshot.dao.VMSnapshotDao;
 
+import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
+import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+
 @Local(value = VirtualMachineManager.class)
 public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMachineManager, Listener {
     private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class);
@@ -266,19 +266,19 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     protected List<DeploymentPlanner> _planners;
     public List<DeploymentPlanner> getPlanners() {
-		return _planners;
-	}
-	public void setPlanners(List<DeploymentPlanner> _planners) {
-		this._planners = _planners;
-	}
+        return _planners;
+    }
+    public void setPlanners(List<DeploymentPlanner> _planners) {
+        this._planners = _planners;
+    }
 
     protected List<HostAllocator> _hostAllocators;
     public List<HostAllocator> getHostAllocators() {
-		return _hostAllocators;
-	}
-	public void setHostAllocators(List<HostAllocator> _hostAllocators) {
-		this._hostAllocators = _hostAllocators;
-	}
+        return _hostAllocators;
+    }
+    public void setHostAllocators(List<HostAllocator> _hostAllocators) {
+        this._hostAllocators = _hostAllocators;
+    }
 
     @Inject
     protected List<StoragePoolAllocator> _storagePoolAllocators;
@@ -369,15 +369,15 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
 
         if (template.getFormat() == ImageFormat.ISO) {
-            this.volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner);
+            volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner);
         } else if (template.getFormat() == ImageFormat.BAREMETAL) {
             // Do nothing
         } else {
-            this.volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner);
+            volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner);
         }
 
         for (Pair<DiskOfferingVO, Long> offering : dataDiskOfferings) {
-            this.volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
+            volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
         }
 
         txn.commit();
@@ -457,11 +457,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
 
         VirtualMachineProfile<T> profile = new VirtualMachineProfileImpl<T>(vm);
+
+        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
+
         s_logger.debug("Cleaning up NICS");
+        List<Command> nicExpungeCommands = hvGuru.finalizeExpungeNics(vm, profile.getNics());
         _networkMgr.cleanupNics(profile);
+
         // Clean up volumes based on the vm's instance id
         List<VolumeVO> rootVol = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT);
-        this.volumeMgr.cleanupVolumes(vm.getId());
+        volumeMgr.cleanupVolumes(vm.getId());
 
         VirtualMachineGuru<T> guru = getVmGuru(vm);
         guru.finalizeExpunge(vm);
@@ -469,7 +474,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         _uservmDetailsDao.deleteDetails(vm.getId());
 
         // send hypervisor-dependent commands before removing
-        HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
         List<Command> finalizeExpungeCommands = hvGuru.finalizeExpunge(vm);
         if(finalizeExpungeCommands != null && finalizeExpungeCommands.size() > 0){
             Long hostId = vm.getHostId() != null ? vm.getHostId() : vm.getLastHostId();
@@ -478,6 +482,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 for (Command command : finalizeExpungeCommands) {
                     cmds.addCommand(command);
                 }
+                if (nicExpungeCommands != null) {
+                    for (Command command : nicExpungeCommands) {
+                        cmds.addCommand(command);
+                    }
+                }
                 _agentMgr.send(hostId, cmds);
                 if(!cmds.isSuccessful()){
                     for (Answer answer : cmds.getAnswers()){
@@ -849,7 +858,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     }
                     _networkMgr.prepare(vmProfile, dest, ctx);
                     if (vm.getHypervisorType() != HypervisorType.BareMetal) {
-                        this.volumeMgr.prepare(vmProfile, dest);
+                        volumeMgr.prepare(vmProfile, dest);
                     }
                     //since StorageMgr succeeded in volume creation, reuse Volume for further tries until current cluster has capacity
                     if(!reuseVolume){
@@ -972,7 +981,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         if (startedVm == null) {
             throw new CloudRuntimeException("Unable to start instance '" + vm.getHostName()
-                            + "' (" + vm.getUuid() + "), see management server log for details");
+                    + "' (" + vm.getUuid() + "), see management server log for details");
         }
 
         return startedVm;
@@ -1071,7 +1080,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.warn("Unable to release some network resources.", e);
         }
 
-        this.volumeMgr.release(profile);
+        volumeMgr.release(profile);
         s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state");
         return true;
     }
@@ -1231,7 +1240,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         try {
             if (vm.getHypervisorType() != HypervisorType.BareMetal) {
-                this.volumeMgr.release(profile);
+                volumeMgr.release(profile);
                 s_logger.debug("Successfully released storage resources for the vm " + vm);
             }
         } catch (Exception e) {
@@ -1350,7 +1359,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
         boolean migrationResult = false;
         try {
-            migrationResult = this.volumeMgr.storageMigration(profile, destPool);
+            migrationResult = volumeMgr.storageMigration(profile, destPool);
 
             if (migrationResult) {
                 //if the vm is migrated to different pod in basic mode, need to reallocate ip
@@ -1437,10 +1446,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         for(NicProfile nic: _networkMgr.getNicProfiles(vm)){
             vmSrc.addNic(nic);
         }
-        
+
         VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
         _networkMgr.prepareNicForMigration(profile, dest);
-        this.volumeMgr.prepareForMigration(profile, dest);
+        volumeMgr.prepareForMigration(profile, dest);
 
         VirtualMachineTO to = toVmTO(profile);
         PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
@@ -1675,7 +1684,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
 
         _networkMgr.prepareNicForMigration(profile, destination);
-        this.volumeMgr.prepareForMigration(profile, destination);
+        volumeMgr.prepareForMigration(profile, destination);
         HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType());
         VirtualMachineTO to = hvGuru.implement(profile);
 
@@ -1692,7 +1701,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         boolean migrated = false;
         try {
             // Migrate the vm and its volume.
-            this.volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool);
+            volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool);
 
             // Put the vm back to running state.
             moveVmOutofMigratingStateOnSuccess(vm, destHost.getId(), work);
@@ -2105,7 +2114,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             }
 
             if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting ))
-            		||  (info != null && (info.state == State.Running && vm.getState() == State.Starting)))
+                    ||  (info != null && (info.state == State.Running && vm.getState() == State.Starting)))
             {
                 s_logger.info("Found vm " + vm.getInstanceName() + " in inconsistent state. " + vm.getState() + " on CS while " +  (info == null ? "Stopped" : "Running") + " on agent");
                 info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped);
@@ -2625,7 +2634,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
             HashMap<String, Pair<String, State>> allStates = startup.getClusterVMStateChanges();
             if (allStates != null){
-                this.fullSync(clusterId, allStates);
+                fullSync(clusterId, allStates);
             }
 
             // initiate the cron job
@@ -2713,7 +2722,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             this.state = state;
             this.vm = vm;
             this.guru = (VirtualMachineGuru<VMInstanceVO>) guru;
-            this.hostUuid = host;
+            hostUuid = host;
         }
 
         public AgentVmInfo(String name, VirtualMachineGuru<? extends VMInstanceVO> guru, VMInstanceVO vm, State state) {
@@ -2846,7 +2855,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             VirtualMachineGuru<VMInstanceVO> vmGuru = getVmGuru(vmVO);
 
             s_logger.debug("Plugging nic for vm " + vm + " in network " + network);
-            
+
             boolean result = false;
             try{
                 result = vmGuru.plugNic(network, nicTO, vmTO, context, dest);
@@ -2856,17 +2865,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     // insert nic's Id into DB as resource_name
                     UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmVO.getAccountId(),
                             vmVO.getDataCenterId(), vmVO.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(),
-                            null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid());                     
+                            null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid());
                     return nic;
                 } else {
                     s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network);
                     return null;
-                }                
+                }
             }finally{
                 if(!result){
                     _networkMgr.removeNic(vmProfile, _nicsDao.findById(nic.getId()));
                 }
-            }            
+            }
         } else if (vm.getState() == State.Stopped) {
             //1) allocate nic
             return _networkMgr.createNicForVm(network, requested, context, vmProfile, false);
@@ -2907,10 +2916,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.warn("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
             throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default.");
         }
-        
+
         // if specified nic is associated with PF/LB/Static NAT
         if(rulesMgr.listAssociatedRulesForGuestNic(nic).size() > 0){
-            throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network 
+            throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network
                     + ", nic has associated Port forwarding or Load balancer or Static NAT rules.");
         }
 
@@ -2928,7 +2937,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network );
                 long isDefault = (nic.isDefaultNic()) ? 1 : 0;
                 UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(),
-                        vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null, 
+                        vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null,
                         isDefault, VirtualMachine.class.getName(), vm.getUuid());
             } else {
                 s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network);
@@ -3081,160 +3090,160 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
     }
 
-        @Override
-        public <T extends VMInstanceVO> T migrateForScale(T vm, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
-                VirtualMachineMigrationException {
-            s_logger.info("Migrating " + vm + " to " + dest);
+    @Override
+    public <T extends VMInstanceVO> T migrateForScale(T vm, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException,
+    VirtualMachineMigrationException {
+        s_logger.info("Migrating " + vm + " to " + dest);
 
-            Long newSvcOfferingId = vm.getServiceOfferingId();
-            long dstHostId = dest.getHost().getId();
-            Host fromHost = _hostDao.findById(srcHostId);
-            if (fromHost == null) {
-                s_logger.info("Unable to find the host to migrate from: " + srcHostId);
-                throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId);
-            }
+        vm.getServiceOfferingId();
+        long dstHostId = dest.getHost().getId();
+        Host fromHost = _hostDao.findById(srcHostId);
+        if (fromHost == null) {
+            s_logger.info("Unable to find the host to migrate from: " + srcHostId);
+            throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId);
+        }
 
-            if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) {
-                s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
-                throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
-            }
+        if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) {
+            s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
+            throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId());
+        }
 
-            VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
+        VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
 
-            long vmId = vm.getId();
-            vm = vmGuru.findById(vmId);
-            if (vm == null) {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("Unable to find the vm " + vm);
-                }
-                throw new ManagementServerException("Unable to find a virtual machine with id " + vmId);
+        long vmId = vm.getId();
+        vm = vmGuru.findById(vmId);
+        if (vm == null) {
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("Unable to find the vm " + vm);
             }
+            throw new ManagementServerException("Unable to find a virtual machine with id " + vmId);
+        }
 
-            if (vm.getState() != State.Running) {
-                if (s_logger.isDebugEnabled()) {
-                    s_logger.debug("VM is not Running, unable to migrate the vm " + vm);
-                }
-                throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString());
+        if (vm.getState() != State.Running) {
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug("VM is not Running, unable to migrate the vm " + vm);
             }
+            throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString());
+        }
 
-            short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
-            if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
-                alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE;
-            } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
-                alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE;
-            }
+        short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE;
+        if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) {
+            alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE;
+        } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) {
+            alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE;
+        }
 
-            VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
-            _networkMgr.prepareNicForMigration(profile, dest);
-            this.volumeMgr.prepareForMigration(profile, dest);
+        VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
+        _networkMgr.prepareNicForMigration(profile, dest);
+        volumeMgr.prepareForMigration(profile, dest);
 
-            VirtualMachineTO to = toVmTO(profile);
-            PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
+        VirtualMachineTO to = toVmTO(profile);
+        PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to);
 
-            ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
-            work.setStep(Step.Prepare);
-            work.setResourceType(ItWorkVO.ResourceType.Host);
-            work.setResourceId(dstHostId);
-            work = _workDao.persist(work);
+        ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId());
+        work.setStep(Step.Prepare);
+        work.setResourceType(ItWorkVO.ResourceType.Host);
+        work.setResourceId(dstHostId);
+        work = _workDao.persist(work);
+
+        PrepareForMigrationAnswer pfma = null;
+        try {
+            pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
+            if (!pfma.getResult()) {
+                String msg = "Unable to prepare for migration due to " + pfma.getDetails();
+                pfma = null;
+                throw new AgentUnavailableException(msg, dstHostId);
+            }
+        } catch (OperationTimedoutException e1) {
+            throw new AgentUnavailableException("Operation timed out", dstHostId);
+        } finally {
+            if (pfma == null) {
+                work.setStep(Step.Done);
+                _workDao.update(work.getId(), work);
+            }
+        }
+
+        vm.setLastHostId(srcHostId);
+        try {
+            if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) {
+                s_logger.info("Migration cancelled because state has changed: " + vm);
+                throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
+            }
+        } catch (NoTransitionException e1) {
+            s_logger.info("Migration cancelled because " + e1.getMessage());
+            throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
+        }
+
+        boolean migrated = false;
+        try {
+            boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
+            MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows);
+            mc.setHostGuid(dest.getHost().getGuid());
 
-            PrepareForMigrationAnswer pfma = null;
             try {
-                pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc);
-                if (!pfma.getResult()) {
-                    String msg = "Unable to prepare for migration due to " + pfma.getDetails();
-                    pfma = null;
-                    throw new AgentUnavailableException(msg, dstHostId);
-                }
-            } catch (OperationTimedoutException e1) {
-                throw new AgentUnavailableException("Operation timed out", dstHostId);
-            } finally {
-                if (pfma == null) {
-                    work.setStep(Step.Done);
-                    _workDao.update(work.getId(), work);
+                MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
+                if (!ma.getResult()) {
+                    s_logger.error("Unable to migrate due to " + ma.getDetails());
+                    return null;
+                }
+            } catch (OperationTimedoutException e) {
+                if (e.isActive()) {
+                    s_logger.warn("Active migration command so scheduling a restart for " + vm);
+                    _haMgr.scheduleRestart(vm, true);
                 }
+                throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId);
             }
 
-            vm.setLastHostId(srcHostId);
             try {
-                if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) {
-                    s_logger.info("Migration cancelled because state has changed: " + vm);
-                    throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm);
+                long newServiceOfferingId = vm.getServiceOfferingId();
+                vm.setServiceOfferingId(oldSvcOfferingId); // release capacity for the old service offering only
+                if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
+                    throw new ConcurrentOperationException("Unable to change the state for " + vm);
                 }
+                vm.setServiceOfferingId(newServiceOfferingId);
             } catch (NoTransitionException e1) {
-                s_logger.info("Migration cancelled because " + e1.getMessage());
-                throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage());
+                throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
             }
 
-            boolean migrated = false;
             try {
-                boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
-                MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows);
-                mc.setHostGuid(dest.getHost().getGuid());
-
-                try {
-                    MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc);
-                    if (!ma.getResult()) {
-                        s_logger.error("Unable to migrate due to " + ma.getDetails());
-                        return null;
-                    }
-                } catch (OperationTimedoutException e) {
-                    if (e.isActive()) {
-                        s_logger.warn("Active migration command so scheduling a restart for " + vm);
-                        _haMgr.scheduleRestart(vm, true);
+                if (!checkVmOnHost(vm, dstHostId)) {
+                    s_logger.error("Unable to complete migration for " + vm);
+                    try {
+                        _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null);
+                    } catch (AgentUnavailableException e) {
+                        s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
                     }
-                    throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId);
+                    cleanup(vmGuru, new VirtualMachineProfileImpl<T>(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
+                    return null;
                 }
+            } catch (OperationTimedoutException e) {
+            }
 
-                try {
-                    long newServiceOfferingId = vm.getServiceOfferingId();
-                    vm.setServiceOfferingId(oldSvcOfferingId); // release capacity for the old service offering only
-                    if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) {
-                        throw new ConcurrentOperationException("Unable to change the state for " + vm);
-                    }
-                    vm.setServiceOfferingId(newServiceOfferingId);
-                } catch (NoTransitionException e1) {
-                    throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage());
-                }
+            migrated = true;
+            return vm;
+        } finally {
+            if (!migrated) {
+                s_logger.info("Migration was unsuccessful.  Cleaning up: " + vm);
 
+                _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone "
+                        + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed.  Please check logs.");
                 try {
-                    if (!checkVmOnHost(vm, dstHostId)) {
-                        s_logger.error("Unable to complete migration for " + vm);
-                        try {
-                            _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null);
-                        } catch (AgentUnavailableException e) {
-                            s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
-                        }
-                        cleanup(vmGuru, new VirtualMachineProfileImpl<T>(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount());
-                        return null;
-                    }
-                } catch (OperationTimedoutException e) {
+                    _agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null);
+                } catch (AgentUnavailableException ae) {
+                    s_logger.info("Looks like the destination Host is unavailable for cleanup");
                 }
 
-                migrated = true;
-                return vm;
-            } finally {
-                if (!migrated) {
-                    s_logger.info("Migration was unsuccessful.  Cleaning up: " + vm);
-
-                    _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone "
-                            + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed.  Please check logs.");
-                    try {
-                        _agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null);
-                    } catch (AgentUnavailableException ae) {
-                        s_logger.info("Looks like the destination Host is unavailable for cleanup");
-                    }
-
-                    try {
-                        stateTransitTo(vm, Event.OperationFailed, srcHostId);
-                    } catch (NoTransitionException e) {
-                        s_logger.warn(e.getMessage());
-                    }
+                try {
+                    stateTransitTo(vm, Event.OperationFailed, srcHostId);
+                } catch (NoTransitionException e) {
+                    s_logger.warn(e.getMessage());
                 }
-
-                work.setStep(Step.Done);
-                _workDao.update(work.getId(), work);
             }
+
+            work.setStep(Step.Done);
+            _workDao.update(work.getId(), work);
         }
+    }
     @Override
     public VMInstanceVO reConfigureVm(VMInstanceVO vm , ServiceOffering oldServiceOffering, boolean reconfiguringOnExistingHost) throws ResourceUnavailableException, ConcurrentOperationException {
 
@@ -3283,7 +3292,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         } catch (AgentUnavailableException e) {
             throw e;
         } finally{
-           // work.setStep(Step.Done);
+            // work.setStep(Step.Done);
             //_workDao.update(work.getId(), work);
             if(!success){
                 _capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); // release the new capacity
@@ -3297,4 +3306,4 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
 
-    }
+}