You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mu...@apache.org on 2012/06/27 04:45:55 UTC

[4/9] moving out VMWAre and Nexus VSM support code into plugins/hypervisors/vmware

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8197f1f0/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java
new file mode 100755
index 0000000..af53dad
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java
@@ -0,0 +1,364 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License.  Citrix Systems, Inc.
+// reserves all rights not expressly granted by 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.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.hypervisor.vmware;
+
+import java.net.URI;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.alert.AlertManager;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.ClusterDetailsDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.exception.DiscoveredWithErrorException;
+import com.cloud.exception.DiscoveryException;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.hypervisor.vmware.manager.VmwareManager;
+import com.cloud.hypervisor.vmware.mo.ClusterMO;
+import com.cloud.hypervisor.vmware.mo.HostMO;
+import com.cloud.hypervisor.vmware.resource.VmwareContextFactory;
+import com.cloud.hypervisor.vmware.resource.VmwareResource;
+import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.cloud.network.NetworkManager;
+import com.cloud.network.dao.CiscoNexusVSMDeviceDao;
+import com.cloud.resource.Discoverer;
+import com.cloud.resource.DiscovererBase;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.Storage.TemplateType;
+import com.cloud.storage.VMTemplateVO;
+import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.user.Account;
+import com.cloud.utils.UriUtils;
+import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.component.Inject;
+import com.vmware.vim25.ClusterDasConfigInfo;
+import com.vmware.vim25.ManagedObjectReference;
+
+@Local(value=Discoverer.class)
+public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter {
+	private static final Logger s_logger = Logger.getLogger(VmwareServerDiscoverer.class);
+	
+	@Inject ClusterDao _clusterDao;
+	@Inject VmwareManager _vmwareMgr;
+    @Inject AlertManager _alertMgr;
+    @Inject VMTemplateDao _tmpltDao;
+    @Inject ClusterDetailsDao _clusterDetailsDao;
+    @Inject HostDao _hostDao;
+    @Inject
+    DataCenterDao _dcDao;
+    @Inject ResourceManager _resourceMgr;
+    @Inject CiscoNexusVSMDeviceDao _nexusDao;
+    @Inject
+    NetworkManager _netmgr;
+    
+    @Override
+    public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long podId, Long clusterId, URI url, 
+    	String username, String password, List<String> hostTags) throws DiscoveryException {
+    	
+    	if(s_logger.isInfoEnabled())
+    		s_logger.info("Discover host. dc: " + dcId + ", pod: " + podId + ", cluster: " + clusterId + ", uri host: " + url.getHost());
+    	
+    	if(podId == null) {
+        	if(s_logger.isInfoEnabled())
+        		s_logger.info("No pod is assigned, assuming that it is not for vmware and skip it to next discoverer"); 
+    		return null;
+    	}
+    	
+        ClusterVO cluster = _clusterDao.findById(clusterId);
+        if(cluster == null || cluster.getHypervisorType() != HypervisorType.VMware) {
+        	if(s_logger.isInfoEnabled())
+        		s_logger.info("invalid cluster id or cluster is not for VMware hypervisors"); 
+    		return null;
+        }
+        
+        List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(clusterId);
+        if(hosts.size() >= _vmwareMgr.getMaxHostsPerCluster()) {
+        	String msg = "VMware cluster " + cluster.getName() + " is too big to add new host now. (current configured cluster size: " + _vmwareMgr.getMaxHostsPerCluster() + ")";
+        	s_logger.error(msg);
+        	throw new DiscoveredWithErrorException(msg);
+        }
+
+        String privateTrafficLabel = null;
+        String publicTrafficLabel = null;
+        String guestTrafficLabel = null;
+        Map<String, String> vsmCredentials = null;
+        
+        privateTrafficLabel = _netmgr.getDefaultManagementTrafficLabel(dcId, HypervisorType.VMware);
+        if (privateTrafficLabel != null) {
+            s_logger.info("Detected private network label : " + privateTrafficLabel);
+        }
+        
+        if (_vmwareMgr.getNexusVSwitchGlobalParameter()) {
+            DataCenterVO zone = _dcDao.findById(dcId);
+            NetworkType zoneType = zone.getNetworkType();
+            if (zoneType != NetworkType.Basic) {
+                publicTrafficLabel = _netmgr.getDefaultPublicTrafficLabel(dcId, HypervisorType.VMware);
+                if (publicTrafficLabel != null) {
+                    s_logger.info("Detected public network label : " + publicTrafficLabel);
+                }
+            }
+            // Get physical network label
+            guestTrafficLabel = _netmgr.getDefaultGuestTrafficLabel(dcId, HypervisorType.VMware);
+            if (guestTrafficLabel != null) {
+                s_logger.info("Detected guest network label : " + guestTrafficLabel);
+            }
+            vsmCredentials = _vmwareMgr.getNexusVSMCredentialsByClusterId(clusterId);
+        }
+
+		VmwareContext context = null;
+		try {
+			context = VmwareContextFactory.create(url.getHost(), username, password);
+            if (privateTrafficLabel != null)
+                context.registerStockObject("privateTrafficLabel", privateTrafficLabel);
+			
+            if (_vmwareMgr.getNexusVSwitchGlobalParameter()) {
+                if (vsmCredentials != null) {
+                    s_logger.info("Stocking credentials of Nexus VSM");
+                    context.registerStockObject("vsmcredentials", vsmCredentials);
+                }
+            }
+			List<ManagedObjectReference> morHosts = _vmwareMgr.addHostToPodCluster(context, dcId, podId, clusterId,
+				URLDecoder.decode(url.getPath()));
+            if (morHosts == null)
+                s_logger.info("Found 0 hosts.");
+            if (privateTrafficLabel != null)
+                context.uregisterStockObject("privateTrafficLabel");
+
+			if(morHosts == null) {
+				s_logger.error("Unable to find host or cluster based on url: " + URLDecoder.decode(url.getPath()));
+				return null;
+			}
+			
+			ManagedObjectReference morCluster = null;
+			Map<String, String> clusterDetails = _clusterDetailsDao.findDetails(clusterId);
+			if(clusterDetails.get("url") != null) {
+				URI uriFromCluster = new URI(UriUtils.encodeURIComponent(clusterDetails.get("url")));
+				morCluster = context.getHostMorByPath(URLDecoder.decode(uriFromCluster.getPath()));
+				
+				if(morCluster == null || !morCluster.getType().equalsIgnoreCase("ClusterComputeResource")) {
+					s_logger.warn("Cluster url does not point to a valid vSphere cluster, url: " + clusterDetails.get("url"));
+					return null;
+				} else {
+					ClusterMO clusterMo = new ClusterMO(context, morCluster);
+					ClusterDasConfigInfo dasConfig = clusterMo.getDasConfig();
+					if(dasConfig != null && dasConfig.getEnabled() != null && dasConfig.getEnabled().booleanValue()) {
+						clusterDetails.put("NativeHA", "true");
+						_clusterDetailsDao.persist(clusterId, clusterDetails);
+					}
+				}
+			}
+			
+			if(!validateDiscoveredHosts(context, morCluster, morHosts)) {
+				if(morCluster == null)
+					s_logger.warn("The discovered host is not standalone host, can not be added to a standalone cluster");
+				else
+					s_logger.warn("The discovered host does not belong to the cluster");
+				return null;
+			}
+
+            Map<VmwareResource, Map<String, String>> resources = new HashMap<VmwareResource, Map<String, String>>();
+			for(ManagedObjectReference morHost : morHosts) {
+	            Map<String, String> details = new HashMap<String, String>();
+	            Map<String, Object> params = new HashMap<String, Object>();
+	            
+	            HostMO hostMo = new HostMO(context, morHost);
+	            details.put("url", hostMo.getHostName());
+	            details.put("username", username);
+	            details.put("password", password);
+	            String guid = morHost.getType() + ":" + morHost.get_value() + "@"+ url.getHost();
+	            details.put("guid", guid);
+	            
+	            params.put("url", hostMo.getHostName());
+	            params.put("username", username);
+	            params.put("password", password);
+	            params.put("zone", Long.toString(dcId));
+	            params.put("pod", Long.toString(podId));
+	            params.put("cluster", Long.toString(clusterId));
+	            params.put("guid", guid);
+                if (privateTrafficLabel != null) {
+                    params.put("private.network.vswitch.name", privateTrafficLabel);
+                }
+                if (publicTrafficLabel != null) {
+                    params.put("public.network.vswitch.name", publicTrafficLabel);
+                }
+                if (guestTrafficLabel != null) {
+                    params.put("guest.network.vswitch.name", guestTrafficLabel);
+                }
+	            
+	            VmwareResource resource = new VmwareResource(); 
+	            try {
+	                resource.configure("VMware", params);
+	            } catch (ConfigurationException e) {
+	                _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, dcId, podId, "Unable to add " + url.getHost(), "Error is " + e.getMessage());
+	                s_logger.warn("Unable to instantiate " + url.getHost(), e);
+	            }
+	            resource.start();
+	            
+	            resources.put(resource, details);
+			}
+            
+            // place a place holder guid derived from cluster ID
+            cluster.setGuid(UUID.nameUUIDFromBytes(String.valueOf(clusterId).getBytes()).toString());
+            _clusterDao.update(clusterId, cluster);
+            
+            return resources;
+		} catch (DiscoveredWithErrorException e) {
+			throw e;
+		} catch (Exception e) {
+			s_logger.warn("Unable to connect to Vmware vSphere server. service address: " + url.getHost());
+			return null;
+		} finally {
+			if(context != null)
+				context.close();
+		}
+    }
+    
+    private boolean validateDiscoveredHosts(VmwareContext context, ManagedObjectReference morCluster, List<ManagedObjectReference> morHosts) throws Exception {
+    	if(morCluster == null) {
+    		for(ManagedObjectReference morHost : morHosts) {
+    			ManagedObjectReference morParent = (ManagedObjectReference)context.getServiceUtil().getDynamicProperty(morHost, "parent");
+    			if(morParent.getType().equalsIgnoreCase("ClusterComputeResource"))
+    				return false;
+    		}
+    	} else {
+    		for(ManagedObjectReference morHost : morHosts) {
+    			ManagedObjectReference morParent = (ManagedObjectReference)context.getServiceUtil().getDynamicProperty(morHost, "parent");
+    			if(!morParent.getType().equalsIgnoreCase("ClusterComputeResource"))
+    				return false;
+    			
+    			if(!morParent.get_value().equals(morCluster.get_value()))
+    				return false;
+    		}
+    	}
+    	
+    	return true;
+    }
+    
+    @Override
+    public void postDiscovery(List<HostVO> hosts, long msId) {
+        // do nothing
+    }
+    
+    @Override
+	public boolean matchHypervisor(String hypervisor) {
+    	if(hypervisor == null)
+    		return true;
+    	
+    	return Hypervisor.HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor);
+    }
+    
+    @Override
+	public Hypervisor.HypervisorType getHypervisorType() {
+    	return Hypervisor.HypervisorType.VMware;
+    }
+    
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        if(s_logger.isInfoEnabled())
+        	s_logger.info("Configure VmwareServerDiscoverer, discover name: " + name);
+        
+        super.configure(name, params);
+        
+        ComponentLocator locator = ComponentLocator.getCurrentLocator();
+        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
+        if (configDao == null) {
+            throw new ConfigurationException("Unable to get the configuration dao.");
+        }
+        
+        createVmwareToolsIso();
+
+		if(s_logger.isInfoEnabled()) {
+			s_logger.info("VmwareServerDiscoverer has been successfully configured");
+		}
+		_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
+        return true;
+    }
+    
+    private void createVmwareToolsIso() {
+        String isoName = "vmware-tools.iso";
+        VMTemplateVO tmplt = _tmpltDao.findByTemplateName(isoName);
+        Long id;
+        if (tmplt == null) {
+            id = _tmpltDao.getNextInSequence(Long.class, "id");
+            VMTemplateVO template = new VMTemplateVO(id, isoName, isoName, ImageFormat.ISO, true, true,
+                    TemplateType.PERHOST, null, null, true, 64,
+                    Account.ACCOUNT_ID_SYSTEM, null, "VMware Tools Installer ISO", false, 1, false, HypervisorType.VMware);
+            _tmpltDao.persist(template);
+        } else {
+            id = tmplt.getId();
+            tmplt.setTemplateType(TemplateType.PERHOST);
+            tmplt.setUrl(null);
+            _tmpltDao.update(id, tmplt);
+        }
+    }
+
+	@Override
+    public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
+	    // TODO Auto-generated method stub
+	    return null;
+    }
+
+	@Override
+    public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
+            List<String> hostTags) {
+		StartupCommand firstCmd = startup[0];
+		if (!(firstCmd instanceof StartupRoutingCommand)) {
+			return null;
+		}
+
+		StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd);
+		if (ssCmd.getHypervisorType() != HypervisorType.VMware) {
+			return null;
+		}
+
+		return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.VMware, details, hostTags);
+    }
+
+	@Override
+    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
+		if (host.getType() != com.cloud.host.Host.Type.Routing || host.getHypervisorType() != HypervisorType.VMware) {
+			return null;
+		}
+		
+		_resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage);
+		return new DeleteHostAnswer(true);
+    }
+	
+    @Override
+    public boolean stop() {
+    	_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
+        return super.stop();
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8197f1f0/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java
new file mode 100644
index 0000000..5822af8
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareHostService.java
@@ -0,0 +1,25 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License.  Citrix Systems, Inc.
+// reserves all rights not expressly granted by 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.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.hypervisor.vmware.manager;
+
+import com.cloud.agent.api.Command;
+import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
+import com.cloud.hypervisor.vmware.util.VmwareContext;
+
+public interface VmwareHostService {
+	VmwareContext getServiceContext(Command cmd);
+	void invalidateServiceContext(VmwareContext context);
+	VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd);
+
+	String getWorkerName(VmwareContext context, Command cmd, int workerSequence);
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8197f1f0/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
new file mode 100755
index 0000000..7d85a96
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java
@@ -0,0 +1,73 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License.  Citrix Systems, Inc.
+// reserves all rights not expressly granted by 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.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.hypervisor.vmware.manager;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.hypervisor.vmware.mo.HostMO;
+import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.cloud.utils.Pair;
+import com.vmware.vim25.ManagedObjectReference;
+
+public interface VmwareManager {
+	public final String CONTEXT_STOCK_NAME = "vmwareMgr";
+	
+	// this limitation comes from the fact that we are using linked clone on shared VMFS storage,
+	// we need to limit the size of vCenter cluster, http://en.wikipedia.org/wiki/VMware_VMFS
+	public final int MAX_HOSTS_PER_CLUSTER = 8;
+
+	String composeWorkerName();
+	
+    String getSystemVMIsoFileNameOnDatastore();
+    String getSystemVMDefaultNicAdapterType();
+    
+	void prepareSecondaryStorageStore(String strStorageUrl);
+	
+	void setupResourceStartupParams(Map<String, Object> params);
+	List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceContext, long dcId, Long podId, Long clusterId,
+			String hostInventoryPath) throws Exception;
+
+	String getManagementPortGroupByHost(HostMO hostMo) throws Exception; 
+	String getServiceConsolePortGroupName();
+	String getManagementPortGroupName();
+	
+	String getSecondaryStorageStoreUrl(long dcId);
+	
+	File getSystemVMKeyFile();
+	
+	VmwareStorageManager getStorageManager();
+	long pushCleanupCheckpoint(String hostGuid, String vmName);
+	void popCleanupCheckpoint(long checkpiont);
+	void gcLeftOverVMs(VmwareContext context);
+	
+	Pair<Integer, Integer> getAddiionalVncPortRange();
+	
+	int getMaxHostsPerCluster();
+	int getRouterExtraPublicNics();
+	
+	boolean beginExclusiveOperation(int timeOutSeconds);
+	void endExclusiveOperation();
+
+    boolean getNexusVSwitchGlobalParameter();
+
+    Map<String, String> getNexusVSMCredentialsByClusterId(Long clusterId);
+
+    String getPrivateVSwitchName(long dcId, HypervisorType hypervisorType);
+
+    String getPublicVSwitchName(long dcId, HypervisorType hypervisorType);
+
+    String getGuestVSwitchName(long dcId, HypervisorType hypervisorType);
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8197f1f0/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
new file mode 100755
index 0000000..debb6fe
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
@@ -0,0 +1,992 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License.  Citrix Systems, Inc.
+// reserves all rights not expressly granted by 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.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.hypervisor.vmware.manager;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.Listener;
+import com.cloud.agent.api.AgentControlAnswer;
+import com.cloud.agent.api.AgentControlCommand;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.cluster.CheckPointManager;
+import com.cloud.cluster.ClusterManager;
+import com.cloud.configuration.Config;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.ClusterDetailsDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.ClusterVSMMapVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.dao.ClusterVSMMapDao;
+import com.cloud.exception.DiscoveredWithErrorException;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.hypervisor.vmware.VmwareCleanupMaid;
+import com.cloud.hypervisor.vmware.manager.VmwareManager;
+import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
+import com.cloud.hypervisor.vmware.manager.VmwareStorageManagerImpl;
+import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
+import com.cloud.hypervisor.vmware.mo.DiskControllerType;
+import com.cloud.hypervisor.vmware.mo.HostFirewallSystemMO;
+import com.cloud.hypervisor.vmware.mo.HostMO;
+import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
+import com.cloud.hypervisor.vmware.mo.TaskMO;
+import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
+import com.cloud.hypervisor.vmware.mo.VmwareHostType;
+import com.cloud.utils.ssh.SshHelper;
+import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.cloud.network.CiscoNexusVSMDeviceVO;
+import com.cloud.network.NetworkManager;
+import com.cloud.network.dao.CiscoNexusVSMDeviceDao;
+import com.cloud.network.router.VirtualNetworkApplianceManager;
+import com.cloud.org.Cluster.ClusterType;
+import com.cloud.secstorage.CommandExecLogDao;
+import com.cloud.serializer.GsonHelper;
+import com.cloud.server.ConfigurationServer;
+import com.cloud.storage.StorageLayer;
+import com.cloud.storage.secondary.SecondaryStorageVmManager;
+import com.cloud.utils.FileUtil;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.Pair;
+import com.cloud.utils.component.ComponentLocator;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.component.Manager;
+import com.cloud.utils.concurrency.NamedThreadFactory;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.GlobalLock;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.script.Script;
+import com.cloud.vm.DomainRouterVO;
+import com.google.gson.Gson;
+import com.vmware.apputils.vim25.ServiceUtil;
+import com.vmware.vim25.HostConnectSpec;
+import com.vmware.vim25.HostPortGroupSpec;
+import com.vmware.vim25.ManagedObjectReference;
+
+@Local(value = {VmwareManager.class})
+public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Listener, Manager {
+    private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class);
+
+    private static final int STARTUP_DELAY = 60000; 				// 60 seconds
+    private static final long DEFAULT_HOST_SCAN_INTERVAL = 600000; 	// every 10 minutes
+
+    private long _hostScanInterval = DEFAULT_HOST_SCAN_INTERVAL;
+    int _timeout;
+
+    private String _name;
+    private String _instance;
+
+    @Inject AgentManager _agentMgr;
+    @Inject
+    protected NetworkManager _netMgr;
+    @Inject HostDao _hostDao;
+    @Inject ClusterDao _clusterDao;
+    @Inject ClusterDetailsDao _clusterDetailsDao;
+    @Inject CommandExecLogDao _cmdExecLogDao;
+    @Inject ClusterManager _clusterMgr;
+    @Inject CheckPointManager _checkPointMgr;
+    @Inject VirtualNetworkApplianceManager _routerMgr;
+    @Inject SecondaryStorageVmManager _ssvmMgr;
+    @Inject CiscoNexusVSMDeviceDao _nexusDao;
+    @Inject ClusterVSMMapDao _vsmMapDao;
+    
+    ConfigurationServer _configServer;
+
+    String _mountParent;
+    StorageLayer _storage;
+
+    String _privateNetworkVSwitchName;
+    String _publicNetworkVSwitchName;
+    String _guestNetworkVSwitchName;
+    boolean _nexusVSwitchActive;
+    String _serviceConsoleName;
+    String _managemetPortGroupName;
+    String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString();
+    String _recycleHungWorker = "false";
+    int _additionalPortRangeStart;
+    int _additionalPortRangeSize;
+    int _maxHostsPerCluster;
+    int _routerExtraPublicNics = 2;
+    
+    String _cpuOverprovisioningFactor = "1";
+    String _reserveCpu = "false";
+    
+    String _memOverprovisioningFactor = "1";
+    String _reserveMem = "false";
+    
+    String _rootDiskController = DiskControllerType.ide.toString();
+    
+    Map<String, String> _storageMounts = new HashMap<String, String>();
+
+    Random _rand = new Random(System.currentTimeMillis());
+    Gson _gson;
+
+    VmwareStorageManager _storageMgr;
+    GlobalLock _exclusiveOpLock = GlobalLock.getInternLock("vmware.exclusive.op");
+
+    private final ScheduledExecutorService _hostScanScheduler = Executors.newScheduledThreadPool(
+            1, new NamedThreadFactory("Vmware-Host-Scan"));
+
+    public VmwareManagerImpl() {
+        _gson = GsonHelper.getGsonLogger();
+        _storageMgr = new VmwareStorageManagerImpl(this);
+    }
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        s_logger.info("Configure VmwareManagerImpl, manager name: " + name);
+
+        _name = name;
+
+        ComponentLocator locator = ComponentLocator.getCurrentLocator();
+        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
+        if (configDao == null) {
+            throw new ConfigurationException("Unable to get the configuration dao.");
+        }
+
+        if(!configDao.isPremium()) {
+            s_logger.error("Vmware component can only run under premium distribution");
+            throw new ConfigurationException("Vmware component can only run under premium distribution");
+        }
+
+        _instance = configDao.getValue(Config.InstanceName.key());
+        if (_instance == null) {
+            _instance = "DEFAULT";
+        }
+        s_logger.info("VmwareManagerImpl config - instance.name: " + _instance);
+
+        _mountParent = configDao.getValue(Config.MountParent.key());
+        if (_mountParent == null) {
+            _mountParent = File.separator + "mnt";
+        }
+
+        if (_instance != null) {
+            _mountParent = _mountParent + File.separator + _instance;
+        }
+        s_logger.info("VmwareManagerImpl config - _mountParent: " + _mountParent);
+
+        String value = (String)params.get("scripts.timeout");
+        _timeout = NumbersUtil.parseInt(value, 1440) * 1000;
+
+        _storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey);
+        if (_storage == null) {
+            value = (String)params.get(StorageLayer.ClassConfigKey);
+            if (value == null) {
+                value = "com.cloud.storage.JavaStorageLayer";
+            }
+
+            try {
+                Class<?> clazz = Class.forName(value);
+                _storage = (StorageLayer)ComponentLocator.inject(clazz);
+                _storage.configure("StorageLayer", params);
+            } catch (ClassNotFoundException e) {
+                throw new ConfigurationException("Unable to find class " + value);
+            }
+        }
+        
+        value = configDao.getValue(Config.VmwareUseNexusVSwitch.key());
+        if(value == null) {
+        	_nexusVSwitchActive = false;
+        }
+        else
+        {
+        	_nexusVSwitchActive = Boolean.parseBoolean(value);
+        }
+
+        _privateNetworkVSwitchName = configDao.getValue(Config.VmwarePrivateNetworkVSwitch.key());
+
+        if (_privateNetworkVSwitchName == null) {
+            _privateNetworkVSwitchName = "vSwitch0";
+        } else {
+            _privateNetworkVSwitchName = "privateEthernetPortProfile";
+        }
+
+        _publicNetworkVSwitchName = configDao.getValue(Config.VmwarePublicNetworkVSwitch.key());
+
+        if (_publicNetworkVSwitchName == null) {
+            _publicNetworkVSwitchName = "vSwitch0";
+        } else {
+            _publicNetworkVSwitchName = "publicEthernetPortProfile";
+        }
+
+        _guestNetworkVSwitchName = configDao.getValue(Config.VmwareGuestNetworkVSwitch.key());
+
+        if (_guestNetworkVSwitchName == null) {
+            _guestNetworkVSwitchName = "vSwitch0";
+        } else {
+            _guestNetworkVSwitchName = "guestEthernetPortProfile";
+        }
+
+        _serviceConsoleName = configDao.getValue(Config.VmwareServiceConsole.key());
+        if(_serviceConsoleName == null) {
+            _serviceConsoleName = "Service Console";
+        }
+        
+        _managemetPortGroupName = configDao.getValue(Config.VmwareManagementPortGroup.key());
+        if(_managemetPortGroupName == null) {
+        	_managemetPortGroupName = "Management Network";
+        }
+        
+        _defaultSystemVmNicAdapterType = configDao.getValue(Config.VmwareSystemVmNicDeviceType.key());
+        if(_defaultSystemVmNicAdapterType == null)
+            _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString();
+        
+        _additionalPortRangeStart = NumbersUtil.parseInt(configDao.getValue(Config.VmwareAdditionalVncPortRangeStart.key()), 59000);
+        if(_additionalPortRangeStart > 65535) {
+        	s_logger.warn("Invalid port range start port (" + _additionalPortRangeStart + ") for additional VNC port allocation, reset it to default start port 59000");
+        	_additionalPortRangeStart = 59000;
+        }
+        
+        _additionalPortRangeSize = NumbersUtil.parseInt(configDao.getValue(Config.VmwareAdditionalVncPortRangeSize.key()), 1000);
+        if(_additionalPortRangeSize < 0 || _additionalPortRangeStart + _additionalPortRangeSize > 65535) {
+        	s_logger.warn("Invalid port range size (" + _additionalPortRangeSize + " for range starts at " + _additionalPortRangeStart);
+        	_additionalPortRangeSize = Math.min(1000, 65535 - _additionalPortRangeStart);
+        }
+        
+        _routerExtraPublicNics = NumbersUtil.parseInt(configDao.getValue(Config.RouterExtraPublicNics.key()), 2);
+        
+        _maxHostsPerCluster = NumbersUtil.parseInt(configDao.getValue(Config.VmwarePerClusterHostMax.key()), VmwareManager.MAX_HOSTS_PER_CLUSTER);
+        _cpuOverprovisioningFactor = configDao.getValue(Config.CPUOverprovisioningFactor.key());
+        if(_cpuOverprovisioningFactor == null || _cpuOverprovisioningFactor.isEmpty())
+        	_cpuOverprovisioningFactor = "1";
+
+        _memOverprovisioningFactor = configDao.getValue(Config.MemOverprovisioningFactor.key());
+        if(_memOverprovisioningFactor == null || _memOverprovisioningFactor.isEmpty())
+        	_memOverprovisioningFactor = "1";
+        
+        _reserveCpu = configDao.getValue(Config.VmwareReserveCpu.key());
+        if(_reserveCpu == null || _reserveCpu.isEmpty())
+        	_reserveCpu = "false";
+        _reserveMem = configDao.getValue(Config.VmwareReserveMem.key());
+        if(_reserveMem == null || _reserveMem.isEmpty())
+        	_reserveMem = "false";
+        
+        _recycleHungWorker = configDao.getValue(Config.VmwareRecycleHungWorker.key());
+        if(_recycleHungWorker == null || _recycleHungWorker.isEmpty())
+            _recycleHungWorker = "false";
+        
+        _rootDiskController = configDao.getValue(Config.VmwareRootDiskControllerType.key());
+        if(_rootDiskController == null || _rootDiskController.isEmpty())
+        	_rootDiskController = DiskControllerType.ide.toString();
+        
+    	s_logger.info("Additional VNC port allocation range is settled at " + _additionalPortRangeStart + " to " + (_additionalPortRangeStart + _additionalPortRangeSize));
+
+        value = configDao.getValue("vmware.host.scan.interval");
+        _hostScanInterval = NumbersUtil.parseLong(value, DEFAULT_HOST_SCAN_INTERVAL);
+        s_logger.info("VmwareManagerImpl config - vmware.host.scan.interval: " + _hostScanInterval);
+
+        ((VmwareStorageManagerImpl)_storageMgr).configure(params);
+
+        if(_configServer == null)
+            _configServer = (ConfigurationServer)ComponentLocator.getComponent(ConfigurationServer.Name);
+        
+        _agentMgr.registerForHostEvents(this, true, true, true);
+
+        s_logger.info("VmwareManagerImpl has been successfully configured");
+        return true;
+    }
+
+    @Override
+    public boolean start() {
+        _hostScanScheduler.scheduleAtFixedRate(getHostScanTask(),
+                STARTUP_DELAY, _hostScanInterval, TimeUnit.MILLISECONDS);
+
+        startupCleanup(_mountParent);
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        _hostScanScheduler.shutdownNow();
+        try {
+            _hostScanScheduler.awaitTermination(3000, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+        }
+
+        shutdownCleanup();
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    public boolean getNexusVSwitchGlobalParameter() {
+        return _nexusVSwitchActive;
+    }
+
+    @Override
+    public String composeWorkerName() {
+        return UUID.randomUUID().toString().replace("-", "");
+    }
+    
+    @Override
+    public String getPrivateVSwitchName(long dcId, HypervisorType hypervisorType) {
+        return _netMgr.getDefaultManagementTrafficLabel(dcId, hypervisorType);
+    }
+    
+    @Override
+    public String getPublicVSwitchName(long dcId, HypervisorType hypervisorType) {
+        return _netMgr.getDefaultPublicTrafficLabel(dcId, hypervisorType);
+    }
+    
+    @Override
+    public String getGuestVSwitchName(long dcId, HypervisorType hypervisorType) {
+        return _netMgr.getDefaultGuestTrafficLabel(dcId, hypervisorType);
+    }
+    
+    @Override
+    public List<ManagedObjectReference> addHostToPodCluster(VmwareContext serviceContext, long dcId, Long podId, Long clusterId,
+            String hostInventoryPath) throws Exception {
+        ManagedObjectReference mor = null;
+        if (serviceContext != null)
+            mor = serviceContext.getHostMorByPath(hostInventoryPath);
+        String privateTrafficLabel = null;
+        privateTrafficLabel = serviceContext.getStockObject("privateTrafficLabel");
+        if (privateTrafficLabel == null) {
+            privateTrafficLabel = _privateNetworkVSwitchName;
+        }
+
+        if(mor != null) {
+            List<ManagedObjectReference> returnedHostList = new ArrayList<ManagedObjectReference>();
+
+            if(mor.getType().equals("ComputeResource")) {
+                ManagedObjectReference[] hosts = (ManagedObjectReference[])serviceContext.getServiceUtil().getDynamicProperty(mor, "host");
+                assert(hosts != null);
+
+                // For ESX host, we need to enable host firewall to allow VNC access
+                HostMO hostMo = new HostMO(serviceContext, hosts[0]);
+                HostFirewallSystemMO firewallMo = hostMo.getHostFirewallSystemMO();
+                if(firewallMo != null) {
+            		if(hostMo.getHostType() == VmwareHostType.ESX) {
+            		    
+	                    firewallMo.enableRuleset("vncServer");
+	                    firewallMo.refreshFirewall();
+            		}
+                }
+
+                // prepare at least one network on the vswitch to enable OVF importing
+                String vlanId = null;
+                if(privateTrafficLabel != null) {
+                	String[] tokens = privateTrafficLabel.split(",");
+                	if(tokens.length == 2)
+                		vlanId = tokens[1];
+                }
+
+                if(!_nexusVSwitchActive) {
+                	HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false);
+                }
+                else {
+                    s_logger.info("Preparing Network on " + privateTrafficLabel);
+                    HypervisorHostHelper.prepareNetwork(privateTrafficLabel, "cloud.private", hostMo, vlanId, null, null, 180000);
+                }
+                returnedHostList.add(hosts[0]);
+                return returnedHostList;
+            } else if(mor.getType().equals("ClusterComputeResource")) {
+                ManagedObjectReference[] hosts = (ManagedObjectReference[])serviceContext.getServiceUtil().getDynamicProperty(mor, "host");
+                assert(hosts != null);
+                
+                if(hosts.length > _maxHostsPerCluster) {
+                	String msg = "vCenter cluster size is too big (current configured cluster size: " + _maxHostsPerCluster + ")";
+                	s_logger.error(msg);
+                	throw new DiscoveredWithErrorException(msg);
+                }
+                
+                for(ManagedObjectReference morHost: hosts) {
+                    // For ESX host, we need to enable host firewall to allow VNC access
+                    HostMO hostMo = new HostMO(serviceContext, morHost);
+                    HostFirewallSystemMO firewallMo = hostMo.getHostFirewallSystemMO();
+                    if(firewallMo != null) {
+                		if(hostMo.getHostType() == VmwareHostType.ESX) {
+	                        firewallMo.enableRuleset("vncServer");
+	                        firewallMo.refreshFirewall();
+                		}
+                    }
+
+                    String vlanId = null;
+                    if(privateTrafficLabel != null) {
+                        String[] tokens = privateTrafficLabel.split(",");
+                        if(tokens.length == 2)
+                            vlanId = tokens[1];
+                    }
+                    
+                    
+                    s_logger.info("Calling prepareNetwork : " + hostMo.getContext().toString());
+                    // prepare at least one network on the vswitch to enable OVF importing
+                    if(!_nexusVSwitchActive) {
+                    	HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false);
+                    }
+                    else {
+                        s_logger.info("Preparing Network on " + privateTrafficLabel);
+                        HypervisorHostHelper.prepareNetwork(privateTrafficLabel, "cloud.private", hostMo, vlanId, null, null, 180000);
+                    }
+                    returnedHostList.add(morHost);
+                }
+                return returnedHostList;
+            } else if(mor.getType().equals("HostSystem")) {
+                // For ESX host, we need to enable host firewall to allow VNC access
+                HostMO hostMo = new HostMO(serviceContext, mor);
+                HostFirewallSystemMO firewallMo = hostMo.getHostFirewallSystemMO();
+                if(firewallMo != null) {
+            		if(hostMo.getHostType() == VmwareHostType.ESX) {
+	                    firewallMo.enableRuleset("vncServer");
+	                    firewallMo.refreshFirewall();
+            		}
+                }
+
+                String vlanId = null;
+                if(privateTrafficLabel != null) {
+                    String[] tokens = privateTrafficLabel.split(",");
+                    if(tokens.length == 2)
+                        vlanId = tokens[1];
+                }
+
+                // prepare at least one network on the vswitch to enable OVF importing
+                if(!_nexusVSwitchActive) {
+                	HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false);
+                }
+                else {
+                    s_logger.info("Preparing Network on " + privateTrafficLabel);
+                    HypervisorHostHelper.prepareNetwork(privateTrafficLabel, "cloud.private", hostMo, vlanId, null, null, 180000);
+                }
+                returnedHostList.add(mor);
+                return returnedHostList;
+            } else {
+                s_logger.error("Unsupport host type " + mor.getType() + ":" + mor.get_value() + " from inventory path: " + hostInventoryPath);
+                return null;
+            }
+        }
+
+        s_logger.error("Unable to find host from inventory path: " + hostInventoryPath);
+        return null;
+    }
+
+    @Deprecated
+    private ManagedObjectReference addHostToVCenterCluster(VmwareContext serviceContext, ManagedObjectReference morCluster,
+            String host, String userName, String password) throws Exception {
+
+        ServiceUtil serviceUtil = serviceContext.getServiceUtil();
+        ManagedObjectReference morHost = serviceUtil.getDecendentMoRef(morCluster, "HostSystem", host);
+        if(morHost == null) {
+            HostConnectSpec hostSpec = new HostConnectSpec();
+            hostSpec.setUserName(userName);
+            hostSpec.setPassword(password);
+            hostSpec.setHostName(host);
+            hostSpec.setForce(true);		// forcely take over the host
+
+            ManagedObjectReference morTask = serviceContext.getService().addHost_Task(morCluster, hostSpec, true, null, null);
+            String taskResult = serviceUtil.waitForTask(morTask);
+            if(!taskResult.equals("sucess")) {
+                s_logger.error("Unable to add host " + host + " to vSphere cluster due to " + TaskMO.getTaskFailureInfo(serviceContext, morTask));
+                throw new CloudRuntimeException("Unable to add host " + host + " to vSphere cluster due to " + taskResult);
+            }
+            serviceContext.waitForTaskProgressDone(morTask);
+
+            // init morHost after it has been created
+            morHost = serviceUtil.getDecendentMoRef(morCluster, "HostSystem", host);
+            if(morHost == null) {
+                throw new CloudRuntimeException("Successfully added host into vSphere but unable to find it later on?!. Please make sure you are either using IP address or full qualified domain name for host");
+            }
+        }
+
+        // For ESX host, we need to enable host firewall to allow VNC access
+        HostMO hostMo = new HostMO(serviceContext, morHost);
+        HostFirewallSystemMO firewallMo = hostMo.getHostFirewallSystemMO();
+        if(firewallMo != null) {
+            firewallMo.enableRuleset("vncServer");
+            firewallMo.refreshFirewall();
+        }
+        return morHost;
+    }
+
+    @Override
+    public String getSecondaryStorageStoreUrl(long dcId) {
+    	List<HostVO> secStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId);
+    	if(secStorageHosts.size() > 0)
+    		return secStorageHosts.get(0).getStorageUrl();
+    	
+        return null;
+    }
+
+	public String getServiceConsolePortGroupName() {
+		return _serviceConsoleName;
+	}
+	
+	public String getManagementPortGroupName() {
+		return _managemetPortGroupName;
+	}
+    
+    @Override
+    public String getManagementPortGroupByHost(HostMO hostMo) throws Exception {
+    	if(hostMo.getHostType() == VmwareHostType.ESXi)
+    		return  this._managemetPortGroupName;
+        return this._serviceConsoleName;
+    }
+    
+    @Override
+    public void setupResourceStartupParams(Map<String, Object> params) {
+        params.put("private.network.vswitch.name", _privateNetworkVSwitchName);
+        params.put("public.network.vswitch.name", _publicNetworkVSwitchName);
+        params.put("guest.network.vswitch.name", _guestNetworkVSwitchName);
+        params.put("vmware.use.nexus.vswitch", _nexusVSwitchActive);
+        params.put("service.console.name", _serviceConsoleName);
+        params.put("management.portgroup.name", _managemetPortGroupName);
+        params.put("cpu.overprovisioning.factor", _cpuOverprovisioningFactor);
+        params.put("vmware.reserve.cpu", _reserveCpu);
+        params.put("mem.overprovisioning.factor", _memOverprovisioningFactor);
+        params.put("vmware.reserve.mem", _reserveMem);
+        params.put("vmware.root.disk.controller", _rootDiskController);
+        params.put("vmware.recycle.hung.wokervm", _recycleHungWorker);
+    }
+
+    @Override
+    public VmwareStorageManager getStorageManager() {
+        return _storageMgr;
+    }
+
+    
+    @Override
+	public long pushCleanupCheckpoint(String hostGuid, String vmName) {
+        return _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostGuid, vmName));
+    }
+    
+    @Override
+	public void popCleanupCheckpoint(long checkpoint) {
+    	_checkPointMgr.popCheckPoint(checkpoint);
+    }
+    
+    @Override
+	public void gcLeftOverVMs(VmwareContext context) {
+    	VmwareCleanupMaid.gcLeftOverVMs(context);
+    }
+
+    @Override
+    public void prepareSecondaryStorageStore(String storageUrl) {
+        String mountPoint = getMountPoint(storageUrl);
+
+        GlobalLock lock = GlobalLock.getInternLock("prepare.systemvm");
+        try {
+            if(lock.lock(3600)) {
+                try {
+                    File patchFolder = new File(mountPoint + "/systemvm");
+                    if(!patchFolder.exists()) {
+                        if(!patchFolder.mkdirs()) {
+                            String msg = "Unable to create systemvm folder on secondary storage. location: " + patchFolder.toString();
+                            s_logger.error(msg);
+                            throw new CloudRuntimeException(msg);
+                        }
+                    }
+
+                    File srcIso = getSystemVMPatchIsoFile();
+                    File destIso = new File(mountPoint + "/systemvm/" + getSystemVMIsoFileNameOnDatastore());
+                    if(!destIso.exists()) {
+                        s_logger.info("Inject SSH key pairs before copying systemvm.iso into secondary storage");
+                        _configServer.updateKeyPairs();
+                        
+	                    try {
+	                        FileUtil.copyfile(srcIso, destIso);
+	                    } catch(IOException e) {
+	                    	s_logger.error("Unexpected exception ", e);
+	                    	
+	                        String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + srcIso.toString() + ", dest location: " + destIso;
+	                        s_logger.error(msg);
+	                        throw new CloudRuntimeException(msg);
+	                    }
+                    } else {
+                    	if(s_logger.isTraceEnabled())
+                    		s_logger.trace("SystemVM ISO file " + destIso.getPath() + " already exists");
+                    }
+                } finally {
+                    lock.unlock();
+                }
+            }
+        } finally {
+            lock.releaseRef();
+        }
+    }
+   
+    @Override
+    public String getSystemVMIsoFileNameOnDatastore() {
+        String version = ComponentLocator.class.getPackage().getImplementationVersion();
+        String fileName = "systemvm-" + version + ".iso";
+        return fileName.replace(':', '-');
+    }
+    
+    @Override
+    public String getSystemVMDefaultNicAdapterType() {
+        return this._defaultSystemVmNicAdapterType;
+    }
+    
+    private File getSystemVMPatchIsoFile() {
+        // locate systemvm.iso
+        URL url = ComponentLocator.class.getProtectionDomain().getCodeSource().getLocation();
+        File file = new File(url.getFile());
+        File isoFile = new File(file.getParent() + "/vms/systemvm.iso");
+        if (!isoFile.exists()) {
+            isoFile = new File("/usr/lib64/cloud/agent/" + "/vms/systemvm.iso");
+            if (!isoFile.exists()) {
+                isoFile = new File("/usr/lib/cloud/agent/" + "/vms/systemvm.iso");
+            }
+        }
+        return isoFile;
+    }
+
+    @Override
+    public File getSystemVMKeyFile() {
+        URL url = ComponentLocator.class.getProtectionDomain().getCodeSource().getLocation();
+        File file = new File(url.getFile());
+
+        File keyFile = new File(file.getParent(), "/scripts/vm/systemvm/id_rsa.cloud");
+        if (!keyFile.exists()) {
+            keyFile = new File("/usr/lib64/cloud/agent" + "/scripts/vm/systemvm/id_rsa.cloud");
+            if (!keyFile.exists()) {
+                keyFile = new File("/usr/lib/cloud/agent" + "/scripts/vm/systemvm/id_rsa.cloud");
+            }
+        }
+        return keyFile;
+    }
+
+    private Runnable getHostScanTask() {
+        return new Runnable() {
+            @Override
+            public void run() {
+                // TODO scan vSphere for newly added hosts.
+                // we are going to both support adding host from CloudStack UI and
+                // adding host via vSphere server
+                //
+                // will implement host scanning later
+            }
+        };
+    }
+
+    @Override
+    public String getMountPoint(String storageUrl) {
+        String mountPoint = null;
+        synchronized(_storageMounts) {
+            mountPoint = _storageMounts.get(storageUrl);
+            if(mountPoint != null) {
+                return mountPoint;
+            }
+
+            URI uri;
+            try {
+                uri = new URI(storageUrl);
+            } catch (URISyntaxException e) {
+                s_logger.error("Invalid storage URL format ", e);
+                throw new CloudRuntimeException("Unable to create mount point due to invalid storage URL format " + storageUrl);
+            }
+            mountPoint = mount(uri.getHost() + ":" + uri.getPath(), _mountParent);
+            if(mountPoint == null) {
+                s_logger.error("Unable to create mount point for " + storageUrl);
+                return "/mnt/sec"; // throw new CloudRuntimeException("Unable to create mount point for " + storageUrl);
+            }
+
+            _storageMounts.put(storageUrl, mountPoint);
+            return mountPoint;
+        }
+    }
+
+    private String setupMountPoint(String parent) {
+        String mountPoint = null;
+        long mshostId = _clusterMgr.getManagementNodeId();
+        for (int i = 0; i < 10; i++) {
+            String mntPt = parent + File.separator + String.valueOf(mshostId) + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
+            File file = new File(mntPt);
+            if (!file.exists()) {
+                if (_storage.mkdir(mntPt)) {
+                    mountPoint = mntPt;
+                    break;
+                }
+            }
+            s_logger.error("Unable to create mount: " + mntPt);
+        }
+
+        return mountPoint;
+    }
+
+    private void startupCleanup(String parent) {
+        s_logger.info("Cleanup mounted NFS mount points used in previous session");
+
+        long mshostId = _clusterMgr.getManagementNodeId();
+
+        // cleanup left-over NFS mounts from previous session
+        String[] mounts = _storage.listFiles(parent + File.separator + String.valueOf(mshostId) + ".*");
+        if(mounts != null && mounts.length > 0) {
+            for(String mountPoint : mounts) {
+                s_logger.info("umount NFS mount from previous session: " + mountPoint);
+
+                String result = null;
+                Script command = new Script(true, "umount", _timeout, s_logger);
+                command.add(mountPoint);
+                result = command.execute();
+                if (result != null) {
+                    s_logger.warn("Unable to umount " + mountPoint + " due to " + result);
+                }
+                File file = new File(mountPoint);
+                if (file.exists()) {
+                    file.delete();
+                }
+            }
+        }
+    }
+
+    private void shutdownCleanup() {
+        s_logger.info("Cleanup mounted NFS mount points used in current session");
+
+        for(String mountPoint : _storageMounts.values()) {
+            s_logger.info("umount NFS mount: " + mountPoint);
+
+            String result = null;
+            Script command = new Script(true, "umount", _timeout, s_logger);
+            command.add(mountPoint);
+            result = command.execute();
+            if (result != null) {
+                s_logger.warn("Unable to umount " + mountPoint + " due to " + result);
+            }
+            File file = new File(mountPoint);
+            if (file.exists()) {
+                file.delete();
+            }
+        }
+    }
+
+    protected String mount(String path, String parent) {
+        String mountPoint = setupMountPoint(parent);
+        if (mountPoint == null) {
+            s_logger.warn("Unable to create a mount point");
+            return null;
+        }
+
+        Script script = null;
+        String result = null;
+        Script command = new Script(true, "mount", _timeout, s_logger);
+        command.add("-t", "nfs");
+        // command.add("-o", "soft,timeo=133,retrans=2147483647,tcp,acdirmax=0,acdirmin=0");
+        if ("Mac OS X".equalsIgnoreCase(System.getProperty("os.name"))) {
+            command.add("-o", "resvport");
+        }
+        command.add(path);
+        command.add(mountPoint);
+        result = command.execute();
+        if (result != null) {
+            s_logger.warn("Unable to mount " + path + " due to " + result);
+            File file = new File(mountPoint);
+            if (file.exists()) {
+                file.delete();
+            }
+            return null;
+        }
+
+        // Change permissions for the mountpoint
+        script = new Script(true, "chmod", _timeout, s_logger);
+        script.add("777", mountPoint);
+        result = script.execute();
+        if (result != null) {
+            s_logger.warn("Unable to set permissions for " + mountPoint + " due to " + result);
+            return null;
+        }
+        return mountPoint;
+    }
+
+    @DB
+    private void updateClusterNativeHAState(HostVO host, StartupCommand cmd) {
+        ClusterVO cluster = _clusterDao.findById(host.getClusterId());
+        if(cluster.getClusterType() == ClusterType.ExternalManaged) {
+            if(cmd instanceof StartupRoutingCommand) {
+                StartupRoutingCommand hostStartupCmd = (StartupRoutingCommand)cmd;
+                Map<String, String> details = hostStartupCmd.getHostDetails();
+
+                if(details.get("NativeHA") != null && details.get("NativeHA").equalsIgnoreCase("true")) {
+                    _clusterDetailsDao.persist(host.getClusterId(), "NativeHA", "true");
+                } else {
+                    _clusterDetailsDao.persist(host.getClusterId(), "NativeHA", "false");
+                }
+            }
+        }
+    }
+
+    @Override @DB
+    public boolean processAnswers(long agentId, long seq, Answer[] answers) {
+        if(answers != null) {
+            for(Answer answer : answers) {
+                String execIdStr = answer.getContextParam("execid");
+                if(execIdStr != null) {
+                    long execId = 0;
+                    try {
+                        execId = Long.parseLong(execIdStr);
+                    } catch(NumberFormatException e) {
+                        assert(false);
+                    }
+
+                    _cmdExecLogDao.expunge(execId);
+                }
+
+                String checkPointIdStr = answer.getContextParam("checkpoint");
+                if(checkPointIdStr != null) {
+                    _checkPointMgr.popCheckPoint(Long.parseLong(checkPointIdStr));
+                }
+                
+                checkPointIdStr = answer.getContextParam("checkpoint2");
+                if(checkPointIdStr != null) {
+                    _checkPointMgr.popCheckPoint(Long.parseLong(checkPointIdStr));
+                }
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean processCommands(long agentId, long seq, Command[] commands) {
+        return false;
+    }
+
+    @Override
+    public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
+        return null;
+    }
+
+    @Override
+    public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) {
+        if(cmd instanceof StartupCommand) {
+            if(host.getHypervisorType() == HypervisorType.VMware) {
+                updateClusterNativeHAState(host, cmd);
+            } else {
+                return;
+            }
+        }
+    }
+    
+    protected final int DEFAULT_DOMR_SSHPORT = 3922;
+    
+    protected boolean shutdownRouterVM(DomainRouterVO router) {
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Try to shutdown router VM " + router.getInstanceName() + " directly.");
+        }
+
+        Pair<Boolean, String> result;
+        try {
+            result = SshHelper.sshExecute(router.getPrivateIpAddress(), DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null,
+                    "poweroff -f");
+
+            if (!result.first()) {
+                s_logger.debug("Unable to shutdown " + router.getInstanceName() + " directly");
+                return false;
+            }
+        } catch (Throwable e) {
+            s_logger.warn("Unable to shutdown router " + router.getInstanceName() + " directly.");
+            return false;
+        }
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Shutdown router " + router.getInstanceName() + " successful.");
+        }
+        return true;
+    }
+
+    @Override
+    public boolean processDisconnect(long agentId, Status state) {
+        return false;
+    }
+
+    @Override
+    public boolean isRecurring() {
+        return false;
+    }
+
+    @Override
+    public int getTimeout() {
+        return 0;
+    }
+
+    @Override
+    public boolean processTimeout(long agentId, long seq) {
+        return false;
+    }
+    
+    @Override
+    public boolean beginExclusiveOperation(int timeOutSeconds) {
+        return _exclusiveOpLock.lock(timeOutSeconds);
+    }
+    
+    @Override
+    public void endExclusiveOperation() {
+        _exclusiveOpLock.unlock();
+    }
+    
+    @Override
+	public Pair<Integer, Integer> getAddiionalVncPortRange() {
+    	return new Pair<Integer, Integer>(_additionalPortRangeStart, _additionalPortRangeSize);
+    }
+    
+    @Override
+    public int getMaxHostsPerCluster() {
+    	return this._maxHostsPerCluster;
+    }
+    
+    @Override
+	public int getRouterExtraPublicNics() {
+		return this._routerExtraPublicNics;
+	}
+
+    @Override
+    public Map<String, String> getNexusVSMCredentialsByClusterId(Long clusterId) {
+        CiscoNexusVSMDeviceVO nexusVSM = null;
+        ClusterVSMMapVO vsmMapVO = null;
+
+        vsmMapVO = _vsmMapDao.findByClusterId(clusterId);
+        long vsmId = 0;
+        if (vsmMapVO != null) {
+            vsmId = vsmMapVO.getVsmId(); 
+            s_logger.info("vsmId is " + vsmId);
+            nexusVSM = _nexusDao.findById(vsmId);
+            s_logger.info("Fetching nexus vsm credentials from database.");
+        }
+        else {
+            s_logger.info("Found empty vsmMapVO.");
+            return null;
+        }        
+
+        Map<String, String> nexusVSMCredentials = new HashMap<String, String>();
+        if (nexusVSM != null) {
+            nexusVSMCredentials.put("vsmip", nexusVSM.getipaddr());
+            nexusVSMCredentials.put("vsmusername", nexusVSM.getUserName());
+            nexusVSMCredentials.put("vsmpassword", nexusVSM.getPassword());
+            s_logger.info("Successfully fetched the credentials of Nexus VSM.");
+        }
+        return nexusVSMCredentials;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/8197f1f0/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java
new file mode 100644
index 0000000..b237291
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManager.java
@@ -0,0 +1,30 @@
+// Copyright 2012 Citrix Systems, Inc. Licensed under the
+// Apache License, Version 2.0 (the "License"); you may not use this
+// file except in compliance with the License.  Citrix Systems, Inc.
+// reserves all rights not expressly granted by 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.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.hypervisor.vmware.manager;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.BackupSnapshotCommand;
+import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
+import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
+import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
+import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
+
+public interface VmwareStorageManager {
+    Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd);
+	Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd);
+	Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd);
+	Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromSnapshotCommand cmd);
+	Answer execute(VmwareHostService hostService, CopyVolumeCommand cmd);
+	Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCommand cmd);
+}