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:22 UTC

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

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;
+    }
 }