// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;

import javax.annotation.PostConstruct;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;

import org.apache.cloudstack.api.command.user.template.CreateTemplateCmd;
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
import org.apache.log4j.Logger;

import com.cloud.agent.api.Answer;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmiBootorResetCommand;
import com.cloud.agent.manager.Commands;
import org.apache.cloudstack.api.command.user.vm.StartVMCmd;

import com.cloud.baremetal.PxeServerManager.PxeServerType;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.DataCenterVO;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.domain.DomainVO;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
import com.cloud.exception.*;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.NetworkVO;
import com.cloud.org.Grouping;
import com.cloud.resource.ResourceManager;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.TemplateType;
import com.cloud.storage.TemplateProfile;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.template.TemplateAdapter;
import com.cloud.template.TemplateAdapter.TemplateAdapterType;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
import com.cloud.user.SSHKeyPair;
import com.cloud.user.User;
import com.cloud.user.UserContext;
import com.cloud.user.*;
import com.cloud.uservm.UserVm;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Manager;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.StateListener;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.*;
import com.cloud.vm.VirtualMachine.Event;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile.Param;

@Local(value={BareMetalVmManager.class, BareMetalVmService.class})
public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMetalVmManager, BareMetalVmService,
		StateListener<State, VirtualMachine.Event, VirtualMachine> {
	private static final Logger s_logger = Logger.getLogger(BareMetalVmManagerImpl.class); 
	@Inject ConfigurationDao _configDao;
	@Inject PxeServerManager _pxeMgr;
	@Inject ResourceManager _resourceMgr;
	
    @Inject protected List<TemplateAdapter> _adapters;

    @PostConstruct
    public void init() {
    }
    
	@Override
	public boolean attachISOToVM(long vmId, long isoId, boolean attach) {
		s_logger.warn("attachISOToVM is not supported by Bare Metal, just fake a true");
		return true;
	}
	
	@Override
	public Volume attachVolumeToVM(AttachVolumeCmd command) {
		s_logger.warn("attachVolumeToVM is not supported by Bare Metal, return null");
		return null;
	}
	
	@Override
	public Volume detachVolumeFromVM(DetachVolumeCmd cmd) {
		s_logger.warn("detachVolumeFromVM is not supported by Bare Metal, return null");
		return null;
	}
	
	@Override
	public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) {
		s_logger.warn("upgradeVirtualMachine is not supported by Bare Metal, return null");
		return null;
	}
	
	@Override
    public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account templateOwner) throws ResourceAllocationException {
		/*Baremetal creates record after host rebooting for imaging, in createPrivateTemplate*/
		return null;
	}
	
	@Override @DB
    public VMTemplateVO createPrivateTemplate(CreateTemplateCmd cmd) throws CloudRuntimeException {
	    Long vmId = cmd.getVmId();
	    if (vmId == null) {
	        throw new InvalidParameterValueException("VM ID is null");
	    }
	    
	    UserVmVO vm = _vmDao.findById(vmId);
	    if (vm == null) {
	        throw new InvalidParameterValueException("Cannot find VM for ID " + vmId);
	    }
	    
	    Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
        HostVO host = _hostDao.findById(hostId);
        if (host == null) {
            throw new InvalidParameterValueException("Cannot find host with id " + hostId);
        }

        List<HostVO> pxes = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, host.getPodId(), host.getDataCenterId());
        if (pxes.size() == 0) {
            throw new CloudRuntimeException("Please add PXE server in Pod before taking image");
        }

        if (pxes.size() > 1) {
        	CloudRuntimeException ex = new CloudRuntimeException("Multiple PXE servers found in Pod " + host.getPodId() + " in Zone with specified id");
            ex.addProxyObject("data_center", host.getDataCenterId(), "zoneId");
            throw ex;
        }

        HostVO pxe = pxes.get(0);
        /*
         * prepare() will check if current account has right for creating
         * template
         */
        TemplateAdapter adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.BareMetal.getName());
        Long userId = UserContext.current().getCallerUserId();
        userId = (userId == null ? User.UID_SYSTEM : userId);
        AccountVO account = _accountDao.findById(vm.getAccountId());
      
        try {
            TemplateProfile tmplProfile;
            tmplProfile = adapter.prepare(false, userId, cmd.getTemplateName(), cmd.getDisplayText(), cmd.getBits(), false, false, cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), false,
                    "BareMetal", cmd.getOsTypeId(), pxe.getDataCenterId(), HypervisorType.BareMetal, account.getAccountName(), account.getDomainId(), "0", true, cmd.getDetails());
 
            if (!_pxeMgr.prepareCreateTemplate(_pxeMgr.getPxeServerType(pxe), pxe.getId(), vm, cmd.getUrl())) {
                throw new Exception("Prepare PXE boot file for host  " + hostId + " failed");
            }

            IpmISetBootDevCommand setBootDev = new IpmISetBootDevCommand(IpmISetBootDevCommand.BootDev.pxe);
            Answer ans = _agentMgr.send(hostId, setBootDev);
            if (!ans.getResult()) {
                throw new Exception("Set host " + hostId + " to PXE boot failed");
            }

            IpmiBootorResetCommand boot = new IpmiBootorResetCommand();
            ans = _agentMgr.send(hostId, boot);
            if (!ans.getResult()) {
                throw new Exception("Boot/Reboot host " + hostId + " failed");
            }

            VMTemplateVO tmpl = adapter.create(tmplProfile);
            s_logger.debug("Create baremetal template for host " + hostId + " successfully, template id:" + tmpl.getId());
            return tmpl;
        } catch (Exception e) {
            s_logger.debug("Create baremetal tempalte for host " + hostId + " failed", e);
            throw new CloudRuntimeException(e.getMessage());
        }
	}

	@Override
	public UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
			StorageUnavailableException, ResourceAllocationException {
		Account caller = UserContext.current().getCaller();

		String accountName = cmd.getAccountName();
		Long domainId = cmd.getDomainId();
		List<Long> networkList = cmd.getNetworkIds();
		String group = cmd.getGroup();

		Account owner = _accountDao.findActiveAccount(accountName, domainId);
		if (owner == null) {
			throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId);
		}

		_accountMgr.checkAccess(caller, null, true, owner);
		long accountId = owner.getId();

		DataCenterVO dc = _dcDao.findById(cmd.getZoneId());
		if (dc == null) {
			throw new InvalidParameterValueException("Unable to find zone: " + cmd.getZoneId());
		}
		
		if(Grouping.AllocationState.Disabled == dc.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())){
			throw new PermissionDeniedException("Cannot perform this operation, Zone is currently disabled: "+ cmd.getZoneId() );
		}

		if (dc.getDomainId() != null) {
			DomainVO domain = _domainDao.findById(dc.getDomainId());
			if (domain == null) {
				throw new CloudRuntimeException("Unable to find the domain " + dc.getDomainId() + " for the zone: " + dc);
			}
			_configMgr.checkZoneAccess(caller, dc);
			_configMgr.checkZoneAccess(owner, dc);
		}

		ServiceOfferingVO offering = _serviceOfferingDao.findById(cmd.getServiceOfferingId());
        if (offering == null || offering.getRemoved() != null) {
            throw new InvalidParameterValueException("Unable to find service offering: " + cmd.getServiceOfferingId());
        }

        // check if account/domain is with in resource limits to create a new vm
        resourceLimitCheck(owner, new Long(offering.getCpu()), new Long(offering.getRamSize()));

		VMTemplateVO template = _templateDao.findById(cmd.getTemplateId());
        // Make sure a valid template ID was specified
        if (template == null || template.getRemoved() != null) {
            throw new InvalidParameterValueException("Unable to use template " + cmd.getTemplateId());
        }
        
        if (template.getTemplateType().equals(TemplateType.SYSTEM)) {
        	throw new InvalidParameterValueException("Unable to use system template " + cmd.getTemplateId()+" to deploy a user vm");
        }

        if (template.getFormat() != Storage.ImageFormat.BAREMETAL) {
        	throw new InvalidParameterValueException("Unable to use non Bare Metal template" + cmd.getTemplateId() +" to deploy a bare metal vm");
        }
        
        String userData = cmd.getUserData();
        byte [] decodedUserData = null;
        if (userData != null) {
            if (userData.length() >= 2 * MAX_USER_DATA_LENGTH_BYTES) {
                throw new InvalidParameterValueException("User data is too long");
            }
            decodedUserData = org.apache.commons.codec.binary.Base64.decodeBase64(userData.getBytes());
            if (decodedUserData.length > MAX_USER_DATA_LENGTH_BYTES){
                throw new InvalidParameterValueException("User data is too long");
            }
            if (decodedUserData.length < 1) {
                throw new InvalidParameterValueException("User data is too short");
            }
        }
        
        // Find an SSH public key corresponding to the key pair name, if one is given
        String sshPublicKey = null;
        if (cmd.getSSHKeyPairName() != null && !cmd.getSSHKeyPairName().equals("")) {
            Account account = UserContext.current().getCaller();
        	SSHKeyPair pair = _sshKeyPairDao.findByName(account.getAccountId(), account.getDomainId(), cmd.getSSHKeyPairName());
    		if (pair == null) {
                throw new InvalidParameterValueException("A key pair with name '" + cmd.getSSHKeyPairName() + "' was not found.");
            }

			sshPublicKey = pair.getPublicKey();
		}

		_accountMgr.checkAccess(caller, null, true, template);

		DataCenterDeployment plan = new DataCenterDeployment(dc.getId());

		s_logger.debug("Allocating in the DB for bare metal vm");
		
		if (dc.getNetworkType() != NetworkType.Basic || networkList != null) {
			s_logger.warn("Bare Metal only supports basical network mode now, switch to baisc network automatically");
		}
		
		Network defaultNetwork = _networkModel.getExclusiveGuestNetwork(dc.getId());
		if (defaultNetwork == null) {
			throw new InvalidParameterValueException("Unable to find a default network to start a vm");
		}
		
		
		networkList = new ArrayList<Long>();
		networkList.add(defaultNetwork.getId());
		
		List<Pair<NetworkVO, NicProfile>> networks = new ArrayList<Pair<NetworkVO, NicProfile>>();
        for (Long networkId : networkList) {
            NetworkVO network = _networkDao.findById(networkId);
            if (network == null) {
                throw new InvalidParameterValueException("Unable to find network by id " + networkId);
            } else {
                if (network.getGuestType() != Network.GuestType.Shared) {
                    //Check account permissions
                    List<NetworkVO> networkMap = _networkDao.listBy(accountId, networkId);
                    if (networkMap == null || networkMap.isEmpty()) {
                        throw new PermissionDeniedException("Unable to create a vm using network with id " + networkId + ", permission denied");
                    }
                } 
                networks.add(new Pair<NetworkVO, NicProfile>(network, null));
            }
        }
        
        long id = _vmDao.getNextInSequence(Long.class, "id");
        
        String hostName = cmd.getName();
        String instanceName = VirtualMachineName.getVmName(id, owner.getId(), _instance);
        if (hostName == null) {
            hostName = instanceName;
        } else {
            //verify hostName (hostname doesn't have to be unique)
            if (!NetUtils.verifyDomainNameLabel(hostName, true)) {
                throw new InvalidParameterValueException("Invalid name. Vm name can contain ASCII letters 'a' through 'z', the digits '0' through '9', " +
                		                                "and the hyphen ('-'), must be between 1 and 63 characters long, and can't start or end with \"-\" and can't start with digit");
            }
        }
        
        UserVmVO vm = new UserVmVO(id, instanceName, cmd.getDisplayName(), template.getId(), HypervisorType.BareMetal,
                template.getGuestOSId(), offering.getOfferHA(), false, domainId, owner.getId(), offering.getId(), userData, hostName, null);
        
        if (sshPublicKey != null) {
            vm.setDetail("SSH.PublicKey", sshPublicKey);
        }

		if (_itMgr.allocate(vm, template, offering, null, null, networks, null, plan, cmd.getHypervisor(), owner) == null) {
			return null;
		}
		

		if (s_logger.isDebugEnabled()) {
			s_logger.debug("Successfully allocated DB entry for " + vm);
		}

		if (s_logger.isDebugEnabled()) {
			s_logger.debug("Successfully allocated DB entry for " + vm);
		}
		UserContext.current().setEventDetails("Vm Id: " + vm.getId());
        UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, cmd.getZoneId(), vm.getId(),
                vm.getHostName(), offering.getId(), template.getId(), HypervisorType.BareMetal.toString(),
                VirtualMachine.class.getName(), vm.getUuid());

        resourceCountIncrement(accountId, new Long(offering.getCpu()), new Long(offering.getRamSize()));

		// Assign instance to the group
		try {
			if (group != null) {
				boolean addToGroup = addInstanceToGroup(Long.valueOf(id), group);
				if (!addToGroup) {
					throw new CloudRuntimeException("Unable to assign Vm to the group " + group);
				}
			}
		} catch (Exception ex) {
			throw new CloudRuntimeException("Unable to assign Vm to the group " + group);
		}

		return vm;
	}
	
	public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
	    UserVmVO vm = _vmDao.findById(cmd.getInstanceId());
	    
		List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, vm.getDataCenterId()); 
	    if (servers.size() == 0) {
	    	throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
	    }
	    HostVO pxeServer = servers.get(0);
	    
	    VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
	    if (template == null || template.getFormat() != Storage.ImageFormat.BAREMETAL) {
	    	throw new InvalidParameterValueException("Invalid template with id = " + vm.getTemplateId());
	    }
	    
		Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>();
		params.put(Param.PxeSeverType, _pxeMgr.getPxeServerType(pxeServer));

		return startVirtualMachine(cmd, params);
	}
	
	
	public UserVm startVirtualMachine(StartVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
        UserVmVO vm = _vmDao.findById(cmd.getInstanceId());

        VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
        if (template == null || template.getFormat() != Storage.ImageFormat.BAREMETAL) {
            throw new InvalidParameterValueException("Invalid template with id = " + vm.getTemplateId());
        }
        
        Map<VirtualMachineProfile.Param, Object> params = null;
        if (vm.isUpdateParameters()) {
            List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, vm.getDataCenterId()); 
            if (servers.size() == 0) {
                throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
            }
            HostVO pxeServer = servers.get(0);
            params = new HashMap<VirtualMachineProfile.Param, Object>();
            params.put(Param.PxeSeverType, _pxeMgr.getPxeServerType(pxeServer));
        }
        
        Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmDetailsPair = super.startVirtualMachine(vm.getId(), cmd.getHostId(), params);
        return vmDetailsPair.first();
    }

	@Override
	public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
		_name = name;

		Map<String, String> configs = _configDao.getConfiguration("AgentManager", params);

		_instance = configs.get("instance.name");
		if (_instance == null) {
			_instance = "DEFAULT";
		}

		String workers = configs.get("expunge.workers");
		int wrks = NumbersUtil.parseInt(workers, 10);

		String time = configs.get("expunge.interval");
		_expungeInterval = NumbersUtil.parseInt(time, 86400);

		time = configs.get("expunge.delay");
		_expungeDelay = NumbersUtil.parseInt(time, _expungeInterval);

		_executor = Executors.newScheduledThreadPool(wrks, new NamedThreadFactory("UserVm-Scavenger"));

		_itMgr.registerGuru(Type.UserBareMetal, this);
		VirtualMachine.State.getStateMachine().registerListener(this);

		s_logger.info("User VM Manager is configured.");

		return true;
	}
	
	@Override
	public boolean finalizeVirtualMachineProfile(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context) {
        UserVmVO vm = profile.getVirtualMachine();
	    Account owner = _accountDao.findById(vm.getAccountId());
	    
	    if (owner == null || owner.getState() == Account.State.disabled) {
	        throw new PermissionDeniedException("The owner of " + vm + " either does not exist or is disabled: " + vm.getAccountId());
	    }
	    
	    PxeServerType pxeType = (PxeServerType) profile.getParameter(Param.PxeSeverType);
	    if (pxeType == null) {
	    	s_logger.debug("This is a normal IPMI start, skip prepartion of PXE server");
	    	return true;
	    }
	    s_logger.debug("This is a PXE start, prepare PXE server first");
	    
	    List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, dest.getPod().getId(), dest.getDataCenter().getId()); 
	    if (servers.size() == 0) {
	    	throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
	    }
	    if (servers.size() > 1) {
	    	throw new CloudRuntimeException("Find more than one PXE server, please make sure there is only one PXE server per zone in pod " + dest.getPod().getId() + " zone " + dest.getDataCenter().getId());
	    }
	    HostVO pxeServer = servers.get(0);
	    
	    if (!_pxeMgr.prepare(pxeType, profile, dest, context, pxeServer.getId())) {
	    	throw new CloudRuntimeException("Pepare PXE server failed");
	    }
	    
	    profile.addBootArgs("PxeBoot");
	    
	    return true;
	}
	
	@Override
	public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context) {
		UserVmVO userVm = profile.getVirtualMachine();
		List<NicVO> nics = _nicDao.listByVmId(userVm.getId());
		for (NicVO nic : nics) {
			NetworkVO network = _networkDao.findById(nic.getNetworkId());
			if (network.getTrafficType() == TrafficType.Guest) {
				userVm.setPrivateIpAddress(nic.getIp4Address());
				userVm.setPrivateMacAddress(nic.getMacAddress());
			}
		}
		_vmDao.update(userVm.getId(), userVm);
		return true;
	}

	@Override
	public void finalizeStop(VirtualMachineProfile<UserVmVO> profile, StopAnswer answer) {
		super.finalizeStop(profile, answer);
	}

	@Override
	public UserVm destroyVm(long vmId) throws ResourceUnavailableException, ConcurrentOperationException {
		return super.destroyVm(vmId);
	}

	@Override
	public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
		return true;
	}

	@Override
	public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Object opaque) {
		if (newState != State.Starting && newState != State.Error && newState != State.Expunging) {
			return true;
		}
		
		if (vo.getHypervisorType() != HypervisorType.BareMetal) {
		    return true;
		}
		
		HostVO host = _hostDao.findById(vo.getHostId());
		if (host == null) {
			s_logger.debug("Skip oldState " + oldState + " to " + "newState " + newState + " transimtion");
			return true;
		}
		_hostDao.loadDetails(host);
		
		if (newState == State.Starting) {
			host.setDetail("vmName", vo.getInstanceName());
			s_logger.debug("Add vmName " + host.getDetail("vmName") + " to host " + host.getId() + " details");
		} else {
			if (host.getDetail("vmName") != null && host.getDetail("vmName").equalsIgnoreCase(vo.getInstanceName())) {
				s_logger.debug("Remove vmName " + host.getDetail("vmName") + " from host " + host.getId() + " details");
				host.getDetails().remove("vmName");
			}
		}
		_hostDao.saveDetails(host);
		
		
		return true;
	}
}
