// 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()) {
            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 1000v");
                    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);
                }
	            
	            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();
    }
}

