// 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.guru;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.Local;

import org.apache.log4j.Logger;

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.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.cluster.CheckPointManager;
import com.cloud.cluster.ClusterManager;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.hypervisor.HypervisorGuruBase;
import com.cloud.hypervisor.vmware.VmwareCleanupMaid;
import com.cloud.hypervisor.vmware.manager.VmwareManager;
import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.secstorage.CommandExecLogDao;
import com.cloud.secstorage.CommandExecLogVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
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.SecondaryStorageVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VmDetailConstants;

@Local(value=HypervisorGuru.class)
public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
	private static final Logger s_logger = Logger.getLogger(VMwareGuru.class);

	@Inject NetworkDao _networkDao;
	@Inject GuestOSDao _guestOsDao;
    @Inject HostDao _hostDao;
    @Inject HostDetailsDao _hostDetailsDao;
    @Inject CommandExecLogDao _cmdExecLogDao;
    @Inject ClusterManager _clusterMgr;
    @Inject VmwareManager _vmwareMgr;
    @Inject SecondaryStorageVmManager _secStorageMgr;
    @Inject CheckPointManager _checkPointMgr;
    @Inject NetworkManager _networkMgr;

    protected VMwareGuru() {
    	super();
    }
    
    @Override
    public HypervisorType getHypervisorType() {
        return HypervisorType.VMware;
    }

    @Override
    public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> vm) {
        VirtualMachineTO to = toVirtualMachineTO(vm);
        to.setBootloader(BootloaderType.HVM);

    	Map<String, String> details = to.getDetails();
    	if(details == null)
    		details = new HashMap<String, String>();
        
    	String nicDeviceType = details.get(VmDetailConstants.NIC_ADAPTER);
        if(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO 
        	|| vm.getVirtualMachine() instanceof SecondaryStorageVmVO) {
        	
        	if(nicDeviceType == null) {
        		details.put(VmDetailConstants.NIC_ADAPTER, _vmwareMgr.getSystemVMDefaultNicAdapterType());
        	} else {
        		try {
        			VirtualEthernetCardType.valueOf(nicDeviceType);
        		} catch (Exception e) {
        			s_logger.warn("Invalid NIC device type " + nicDeviceType + " is specified in VM details, switch to default E1000");
            		details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
        		}
        	}
        } else {
        	// for user-VM, use E1000 as default
        	if(nicDeviceType == null) {
        		details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
        	} else {
        		try {
        			VirtualEthernetCardType.valueOf(nicDeviceType);
        		} catch (Exception e) {
        			s_logger.warn("Invalid NIC device type " + nicDeviceType + " is specified in VM details, switch to default E1000");
            		details.put(VmDetailConstants.NIC_ADAPTER, VirtualEthernetCardType.E1000.toString());
        		}
        	}
        }
    	to.setDetails(details);

    	if(vm.getVirtualMachine() instanceof DomainRouterVO) {
    		List<NicProfile> nicProfiles = vm.getNics();
    		NicProfile publicNicProfile = null;
    		
    		for(NicProfile nicProfile : nicProfiles) {
    			if(nicProfile.getTrafficType() == TrafficType.Public) {
    				publicNicProfile = nicProfile;
    				break;
    			}
    		}
    		
    		if(publicNicProfile != null) {
	    		NicTO[] nics = to.getNics();

	    		// reserve extra NICs
	    		NicTO[] expandedNics = new NicTO[nics.length + _vmwareMgr.getRouterExtraPublicNics()];
	    		int i = 0;
	    		int deviceId = -1;
	    		for(i = 0; i < nics.length; i++) {
	    			expandedNics[i] = nics[i];
	    			if(nics[i].getDeviceId() > deviceId)
	    				deviceId = nics[i].getDeviceId();
	    		}
	    		deviceId++;
	    		
	    		long networkId = publicNicProfile.getNetworkId();
	    		NetworkVO network = _networkDao.findById(networkId);
	    		
	    		for(; i < nics.length + _vmwareMgr.getRouterExtraPublicNics(); i++) {
	    			NicTO nicTo = new NicTO();
	    			
	    			nicTo.setDeviceId(deviceId++);
	    			nicTo.setBroadcastType(publicNicProfile.getBroadcastType());
	    			nicTo.setType(publicNicProfile.getTrafficType());
	    			nicTo.setIp("0.0.0.0");
	    			nicTo.setNetmask("255.255.255.255");
	    			
	    			try {
	    				String mac = _networkMgr.getNextAvailableMacAddressInNetwork(networkId);
						nicTo.setMac(mac);
					} catch (InsufficientAddressCapacityException e) {
						throw new CloudRuntimeException("unable to allocate mac address on network: " + networkId);
					}
	    			nicTo.setDns1(publicNicProfile.getDns1());
	    			nicTo.setDns2(publicNicProfile.getDns2());
	    	        if (publicNicProfile.getGateway() != null) {
	    	        	nicTo.setGateway(publicNicProfile.getGateway());
	    	        } else {
	    	        	nicTo.setGateway(network.getGateway());
	    	        }
	    	        nicTo.setDefaultNic(false);
	    	        nicTo.setBroadcastUri(publicNicProfile.getBroadCastUri());
	    	        nicTo.setIsolationuri(publicNicProfile.getIsolationUri());

	    	        Integer networkRate = _networkMgr.getNetworkRate(network.getId(), null);
	    	        nicTo.setNetworkRateMbps(networkRate);
	    	        
	    	        expandedNics[i] = nicTo;
	    		}
	    		
	    		to.setNics(expandedNics);
    		}
    		
    		StringBuffer sbMacSequence = new StringBuffer();
        	for(NicTO nicTo : sortNicsByDeviceId(to.getNics())) {
    			sbMacSequence.append(nicTo.getMac()).append("|");
        	}
    		sbMacSequence.deleteCharAt(sbMacSequence.length() - 1);
    		String bootArgs = to.getBootArgs();
    		to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString());
    	}

        // Determine the VM's OS description
        GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
        to.setOs(guestOS.getDisplayName());
        return to;
    }
    
    private NicTO[] sortNicsByDeviceId(NicTO[] nics) {

        List<NicTO> listForSort = new ArrayList<NicTO>();
        for (NicTO nic : nics) {
            listForSort.add(nic);
        }
        Collections.sort(listForSort, new Comparator<NicTO>() {

            @Override
            public int compare(NicTO arg0, NicTO arg1) {
                if (arg0.getDeviceId() < arg1.getDeviceId()) {
                    return -1;
                } else if (arg0.getDeviceId() == arg1.getDeviceId()) {
                    return 0;
                }

                return 1;
            }
        });

        return listForSort.toArray(new NicTO[0]);
    }
    
    @Override @DB
    public long getCommandHostDelegation(long hostId, Command cmd) {
    	boolean needDelegation = false;
    	
    	if(cmd instanceof PrimaryStorageDownloadCommand || 
    		cmd instanceof BackupSnapshotCommand ||
    		cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
    		cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
    		cmd instanceof CopyVolumeCommand ||
    		cmd instanceof CreateVolumeFromSnapshotCommand) {
    		needDelegation = true;
    	}

    	if(needDelegation) {
    		HostVO host = _hostDao.findById(hostId);
    		assert(host != null);
    		assert(host.getHypervisorType() == HypervisorType.VMware);
    		long dcId = host.getDataCenterId();
    		
    		Pair<HostVO, SecondaryStorageVmVO> cmdTarget = _secStorageMgr.assignSecStorageVm(dcId, cmd);
    		if(cmdTarget != null) {
    			// TODO, we need to make sure agent is actually connected too
    			cmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
    		    Map<String, String> hostDetails = _hostDetailsDao.findDetails(hostId);
    		    cmd.setContextParam("guid", resolveNameInGuid(hostDetails.get("guid")));
    		    cmd.setContextParam("username", hostDetails.get("username"));
    		    cmd.setContextParam("password", hostDetails.get("password"));
    			cmd.setContextParam("serviceconsole", _vmwareMgr.getServiceConsolePortGroupName());
    			cmd.setContextParam("manageportgroup", _vmwareMgr.getManagementPortGroupName());
    			
    			CommandExecLogVO execLog = new CommandExecLogVO(cmdTarget.first().getId(), cmdTarget.second().getId(), cmd.getClass().getSimpleName(), 1);
    			_cmdExecLogDao.persist(execLog);
    			cmd.setContextParam("execid", String.valueOf(execLog.getId()));
    			
    			if(cmd instanceof BackupSnapshotCommand || 
    				cmd instanceof CreatePrivateTemplateFromVolumeCommand || 
    				cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
    				cmd instanceof CopyVolumeCommand ||
    				cmd instanceof CreateVolumeFromSnapshotCommand) {
    				
    				String workerName = _vmwareMgr.composeWorkerName();
    				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 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2));
                    cmd.setContextParam("worker2", workerName2);
                    cmd.setContextParam("checkpoint2", String.valueOf(checkPointId2));
    			}
    			
    			return cmdTarget.first().getId();
    		}
    	}
  
    	return hostId;
    }
    
    public boolean trackVmHostChange() {
    	return true;
    }
    
    private static String resolveNameInGuid(String guid) {
    	String tokens[] = guid.split("@");
    	assert(tokens.length == 2);

    	String vCenterIp = NetUtils.resolveToIp(tokens[1]);
    	if(vCenterIp == null) {
    		s_logger.error("Fatal : unable to resolve vCenter address " + tokens[1] + ", please check your DNS configuration");
    		return guid;
    	}
    	
    	if(vCenterIp.equals(tokens[1]))
    		return guid;
    	
    	return tokens[0] + "@" + vCenterIp;
    }
}
