/**
 *  Copyright (C) 2010 Cloud.com, Inc.  All rights reserved.
 *
 * This software is licensed under the GNU General Public License v3 or later.
 *
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package com.cloud.agent.manager;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.channels.ClosedChannelException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
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.StartupCommandProcessor;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckHealthCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.GetHostStatsAnswer;
import com.cloud.agent.api.GetHostStatsCommand;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.PingAnswer;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PoolEjectCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.ShutdownCommand;
import com.cloud.agent.api.StartupAnswer;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalDhcpCommand;
import com.cloud.agent.api.StartupExternalFirewallCommand;
import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
import com.cloud.agent.api.StartupProxyCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.StartupTrafficMonitorCommand;
import com.cloud.agent.api.UnsupportedAnswer;
import com.cloud.agent.api.UpdateHostPasswordCommand;
import com.cloud.agent.manager.allocator.PodAllocator;
import com.cloud.agent.transport.Request;
import com.cloud.agent.transport.Response;
import com.cloud.alert.AlertManager;
import com.cloud.api.ApiConstants;
import com.cloud.api.commands.UpdateHostPasswordCmd;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.cluster.ManagementServerNode;
import com.cloud.cluster.StackMaid;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterDetailsVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodCluster;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.DataCenterIpAddressDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConnectionException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.UnsupportedVersionException;
import com.cloud.ha.HighAvailabilityManager;
import com.cloud.ha.HighAvailabilityManager.WorkType;
import com.cloud.host.DetailVO;
import com.cloud.host.Host;
import com.cloud.host.Host.HostAllocationState;
import com.cloud.host.Host.Type;
import com.cloud.host.HostStats;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.Status.Event;
import com.cloud.host.dao.HostDao;
import com.cloud.host.dao.HostDetailsDao;
import com.cloud.host.dao.HostTagsDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase;
import com.cloud.network.IPAddressVO;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.resource.ServerResource;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StoragePoolVO;
import com.cloud.storage.StorageService;
import com.cloud.storage.dao.StoragePoolDao;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.resource.DummySecondaryStorageResource;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.utils.ActionDelegate;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.Adapters;
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.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.HypervisorVersionChangedException;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.nio.HandlerFactory;
import com.cloud.utils.nio.Link;
import com.cloud.utils.nio.NioServer;
import com.cloud.utils.nio.Task;
import com.cloud.utils.time.InaccurateClock;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.VMInstanceDao;

import edu.emory.mathcs.backport.java.util.Collections;

/**
 * Implementation of the Agent Manager. This class controls the connection to the agents.
 *
 * @config {@table || Param Name | Description | Values | Default || || port | port to listen on for agent connection. | Integer
 *         | 8250 || || workers | # of worker threads | Integer | 5 || || router.template.id | default id for template | Integer
 *         | 1 || || router.ram.size | default ram for router vm in mb | Integer | 128 || || router.ip.address | ip address for
 *         the router | ip | 10.1.1.1 || || wait | Time to wait for control commands to return | seconds | 1800 || || domain |
 *         domain for domain routers| String | foo.com || || alert.wait | time to wait before alerting on a disconnected agent |
 *         seconds | 1800 || || update.wait | time to wait before alerting on a updating agent | seconds | 600 || ||
 *         ping.interval | ping interval in seconds | seconds | 60 || || instance.name | Name of the deployment String |
 *         required || || start.retry | Number of times to retry start | Number | 2 || || ping.timeout | multiplier to
 *         ping.interval before announcing an agent has timed out | float | 2.0x || || router.stats.interval | interval to
 *         report router statistics | seconds | 300s || * }
 **/
@Local(value = { AgentManager.class })
public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
    private static final Logger s_logger = Logger.getLogger(AgentManagerImpl.class);

    protected ConcurrentHashMap<Long, AgentAttache> _agents = new ConcurrentHashMap<Long, AgentAttache>(10007);
    protected List<Pair<Integer, Listener>> _hostMonitors = new ArrayList<Pair<Integer, Listener>>(17);
    protected List<Pair<Integer, Listener>> _cmdMonitors = new ArrayList<Pair<Integer, Listener>>(17);
    protected List<Pair<Integer, StartupCommandProcessor>> _creationMonitors = new ArrayList<Pair<Integer, StartupCommandProcessor>>(17);
    protected List<Long> _loadingAgents = new ArrayList<Long>();
    protected int _monitorId = 0;

    protected NioServer _connection;
    @Inject
    protected HostDao _hostDao = null;
    @Inject
    protected HostDetailsDao _detailsDao = null;
    @Inject
    protected DataCenterDao _dcDao = null;
    @Inject
    protected DataCenterIpAddressDao _privateIPAddressDao = null;
    @Inject
    protected IPAddressDao _publicIPAddressDao = null;
    @Inject
    protected HostPodDao _podDao = null;
    @Inject(adapter = PodAllocator.class)
    protected Adapters<PodAllocator> _podAllocators = null;
    @Inject
    protected VMInstanceDao _vmDao = null;
    @Inject
    protected CapacityDao _capacityDao = null;
    @Inject
    protected ConfigurationDao _configDao = null;
    @Inject
    protected StoragePoolDao _storagePoolDao = null;
    @Inject
    protected StoragePoolHostDao _storagePoolHostDao = null;
    @Inject
    protected HostDetailsDao _hostDetailsDao = null;
    @Inject
    protected ClusterDao _clusterDao = null;
    @Inject
    protected ClusterDetailsDao _clusterDetailsDao = null;
    @Inject
    protected HostTagsDao _hostTagsDao = null;
    @Inject
    protected VolumeDao _volumeDao = null;

    protected int _port;

    @Inject
    protected HighAvailabilityManager _haMgr = null;
    @Inject
    protected AlertManager _alertMgr = null;

    @Inject
    protected AccountManager _accountMgr = null;

    @Inject
    protected VirtualMachineManager _vmMgr = null;

    @Inject StorageService _storageSvr = null;
    @Inject StorageManager _storageMgr = null;

    protected int _retry = 2;

    protected String _name;
    protected String _instance;

    protected int _wait;
    protected int _updateWait;
    protected int _alertWait;
    protected long _nodeId = -1;

    protected Random _rand = new Random(System.currentTimeMillis());

    protected int _pingInterval;
    protected long _pingTimeout;
    protected AgentMonitor _monitor = null;

    protected ExecutorService _executor;

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

        final ComponentLocator locator = ComponentLocator.getCurrentLocator();
        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
        if (configDao == null) {
            throw new ConfigurationException("Unable to get the configuration dao.");
        }

        final Map<String, String> configs = configDao.getConfiguration("AgentManager", params);
        _port = NumbersUtil.parseInt(configs.get("port"), 8250);
        final int workers = NumbersUtil.parseInt(configs.get("workers"), 5);

        String value = configs.get(Config.PingInterval.toString());
        _pingInterval = NumbersUtil.parseInt(value, 60);

        value = configs.get(Config.Wait.toString());
        _wait = NumbersUtil.parseInt(value, 1800);

        value = configs.get(Config.AlertWait.toString());
        _alertWait = NumbersUtil.parseInt(value, 1800);

        value = configs.get(Config.UpdateWait.toString());
        _updateWait = NumbersUtil.parseInt(value, 600);

        value = configs.get(Config.PingTimeout.toString());
        final float multiplier = value != null ? Float.parseFloat(value) : 2.5f;
        _pingTimeout = (long) (multiplier * _pingInterval);

        s_logger.info("Ping Timeout is " + _pingTimeout);

        value = configs.get(Config.DirectAgentLoadSize.key());
        int threads = NumbersUtil.parseInt(value, 16);

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

        _nodeId = ManagementServerNode.getManagementServerId();
        s_logger.info("Configuring AgentManagerImpl. management server node id(msid): " + _nodeId);
        
        long lastPing = (System.currentTimeMillis() >> 10) - _pingTimeout;
        _hostDao.markHostsAsDisconnected(_nodeId, lastPing);

        _monitor = ComponentLocator.inject(AgentMonitor.class, _nodeId, _hostDao, _vmDao, _dcDao, _podDao, this, _alertMgr, _pingTimeout);
        registerForHostEvents(_monitor, true, true, false);

        _executor = new ThreadPoolExecutor(threads, threads, 60l, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new NamedThreadFactory("AgentTaskPool"));

        _connection = new NioServer("AgentManager", _port, workers + 10, this);

        s_logger.info("Listening on " + _port + " with " + workers + " workers");
        return true;
    }

    @Override
    public boolean isHostNativeHAEnabled(long hostId) {
        HostVO host = _hostDao.findById(hostId);
        if (host.getClusterId() != null) {
            ClusterDetailsVO detail = _clusterDetailsDao.findDetail(host.getClusterId(), "NativeHA");
            return detail == null ? false : Boolean.parseBoolean(detail.getValue());
        }
        return false;
    }

    @Override
    public Task create(Task.Type type, Link link, byte[] data) {
        return new AgentHandler(type, link, data);
    }

    @Override
    public int registerForHostEvents(final Listener listener, boolean connections, boolean commands, boolean priority) {
        synchronized (_hostMonitors) {
            _monitorId++;
            if (connections) {
                if (priority) {
                    _hostMonitors.add(0, new Pair<Integer, Listener>(_monitorId, listener));
                } else {
                    _hostMonitors.add(new Pair<Integer, Listener>(_monitorId, listener));
                }
            }
            if (commands) {
                if (priority) {
                    _cmdMonitors.add(0, new Pair<Integer, Listener>(_monitorId, listener));
                } else {
                    _cmdMonitors.add(new Pair<Integer, Listener>(_monitorId, listener));
                }
            }
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Registering listener " + listener.getClass().getSimpleName() + " with id " + _monitorId);
            }
            return _monitorId;
        }
    }

    @Override
    public int registerForInitialConnects(final StartupCommandProcessor creator,boolean priority) {
        synchronized (_hostMonitors) {
            _monitorId++;

            if (priority) {
                _creationMonitors.add(0, new Pair<Integer, StartupCommandProcessor>(
                        _monitorId, creator));
            } else {
                _creationMonitors.add(0, new Pair<Integer, StartupCommandProcessor>(
                        _monitorId, creator));
            }
        }

        return _monitorId;
    }

    @Override
    public void unregisterForHostEvents(final int id) {
        s_logger.debug("Deregistering " + id);
        _hostMonitors.remove(id);
    }

    private AgentControlAnswer handleControlCommand(AgentAttache attache, final AgentControlCommand cmd) {
        AgentControlAnswer answer = null;

        for (Pair<Integer, Listener> listener : _cmdMonitors) {
            answer = listener.second().processControlCommand(attache.getId(), cmd);

            if (answer != null) {
                return answer;
            }
        }

        s_logger.warn("No handling of agent control command: " + cmd + " sent from " + attache.getId());
        return new AgentControlAnswer(cmd);
    }

    public void handleCommands(AgentAttache attache, final long sequence, final Command[] cmds) {
        for (Pair<Integer, Listener> listener : _cmdMonitors) {
            boolean processed = listener.second().processCommands(attache.getId(), sequence, cmds);
            if (s_logger.isTraceEnabled()) {
                s_logger.trace("SeqA " + attache.getId() + "-" + sequence + ": " + (processed ? "processed" : "not processed") + " by " + listener.getClass());
            }
        }
    }

    @Override
    public void notifyAnswersToMonitors(long agentId, long seq, Answer[] answers) {
        for (Pair<Integer, Listener> listener : _cmdMonitors) {
            listener.second().processAnswers(agentId, seq, answers);
        }
    }

    public AgentAttache findAttache(long hostId) {
        AgentAttache attache = null;
        synchronized (_agents) {
            attache = _agents.get(hostId);
        }
        return attache;
    }

    @Override
    public Set<Long> getConnectedHosts() {
        // make the returning set be safe for concurrent iteration
        final HashSet<Long> result = new HashSet<Long>();

        synchronized (_agents) {
            final Set<Long> s = _agents.keySet();
            for (final Long id : s) {
                result.add(id);
            }
        }
        return result;
    }

    @Override
    public List<PodCluster> listByDataCenter(long dcId) {
        List<HostPodVO> pods = _podDao.listByDataCenterId(dcId);
        ArrayList<PodCluster> pcs = new ArrayList<PodCluster>();
        for (HostPodVO pod : pods) {
            List<ClusterVO> clusters = _clusterDao.listByPodId(pod.getId());
            if (clusters.size() == 0) {
                pcs.add(new PodCluster(pod, null));
            } else {
                for (ClusterVO cluster : clusters) {
                    pcs.add(new PodCluster(pod, cluster));
                }
            }
        }
        return pcs;
    }

    @Override
    public List<PodCluster> listByPod(long podId) {
        ArrayList<PodCluster> pcs = new ArrayList<PodCluster>();
        HostPodVO pod = _podDao.findById(podId);
        if (pod == null) {
            return pcs;
        }
        List<ClusterVO> clusters = _clusterDao.listByPodId(pod.getId());
        if (clusters.size() == 0) {
            pcs.add(new PodCluster(pod, null));
        } else {
            for (ClusterVO cluster : clusters) {
                pcs.add(new PodCluster(pod, cluster));
            }
        }
        return pcs;
    }

    protected AgentAttache handleDirectConnect(ServerResource resource, StartupCommand[] startup, Map<String, String> details, boolean old, List<String> hostTags, String allocationState, boolean forRebalance)
            throws ConnectionException {
        if (startup == null) {
            return null;
        }
        HostVO server = createHost(startup, resource, details, old, hostTags, allocationState);
        if (server == null) {
            return null;
        }

        long id = server.getId();

        AgentAttache attache = createAttache(id, server, resource);
        StartupAnswer[] answers = new StartupAnswer[startup.length];
        for (int i = 0; i < answers.length; i++) {
            answers[i] = new StartupAnswer(startup[i], attache.getId(), _pingInterval);
        }

        attache.process(answers);

        attache = notifyMonitorsOfConnection(attache, startup, forRebalance);

        return attache;
    }

    @Override
    public Answer sendToSecStorage(HostVO ssHost, Command cmd) {
        if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) {
            return  easySend(ssHost.getId(), cmd);
        } else if ( ssHost.getType() == Host.Type.SecondaryStorage) {
            return  sendToSSVM(ssHost.getDataCenterId(), cmd);
        } else {
            String msg = "do not support Secondary Storage type " + ssHost.getType();
            s_logger.warn(msg);
            return new Answer(cmd, false, msg);
        }
    }


    @Override
    public HostVO getSSAgent(HostVO ssHost) {
        if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) {
            return  ssHost;
        } else if ( ssHost.getType() == Host.Type.SecondaryStorage) {
            Long dcId = ssHost.getDataCenterId();
            List<HostVO> ssAHosts = _hostDao.listSecondaryStorageVM(dcId);
            if (ssAHosts == null || ssAHosts.isEmpty() ) {
                return null;
            }
            Collections.shuffle(ssAHosts);
            return ssAHosts.get(0);
        }
        return null;
    }


    @Override
    public long sendToSecStorage(HostVO ssHost, Command cmd, Listener listener) {
        if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) {
            return  gatherStats(ssHost.getId(), cmd, listener);
        } else if ( ssHost.getType() == Host.Type.SecondaryStorage) {
            return  sendToSSVM(ssHost.getDataCenterId(), cmd, listener);
        } else {
            s_logger.warn("do not support Secondary Storage type " + ssHost.getType());
        }
        return -1;
    }


    private long sendToSSVM(final long dcId, final Command cmd, final Listener listener) {
        List<HostVO> ssAHosts = _hostDao.listSecondaryStorageVM(dcId);
        if (ssAHosts == null || ssAHosts.isEmpty() ) {
            return -1;
        }
        Collections.shuffle(ssAHosts);
        HostVO ssAhost = ssAHosts.get(0);
        try {
            return send(ssAhost.getId(), new Commands(cmd), listener);
        } catch (final AgentUnavailableException e) {
            return -1;
        }
    }

    private Answer sendToSSVM(final long dcId, final Command cmd) {
        List<HostVO> ssAHosts = _hostDao.listSecondaryStorageVM(dcId);
        if (ssAHosts == null || ssAHosts.isEmpty() ) {
            return new Answer(cmd, false, "can not find secondary storage VM agent for data center " + dcId);
        }
        Collections.shuffle(ssAHosts);
        HostVO ssAhost = ssAHosts.get(0);
        return easySend(ssAhost.getId(), cmd);
    }

    @Override
    public Answer sendTo(Long dcId, HypervisorType type, Command cmd) {
        List<ClusterVO> clusters = _clusterDao.listByDcHyType(dcId, type.toString());
        int retry = 0;
        for (ClusterVO cluster : clusters) {
            List<HostVO> hosts = _hostDao.listBy(Host.Type.Routing, cluster.getId(), null, dcId);
            for (HostVO host : hosts) {
                retry++;
                if (retry > _retry) {
                    return null;
                }
                Answer answer = null;
                try {
                    answer = easySend(host.getId(), cmd);
                } catch (Exception e) {
                }
                if (answer != null) {
                    return answer;
                }
            }
        }
        return null;
    }

    @Override
    @DB
    public boolean deleteHost(long hostId, boolean isForced, boolean forceDestroy, User caller) {

        // Check if the host exists
        HostVO host = _hostDao.findById(hostId);
        if (host == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Host: " + hostId + " does not even exist.  Delete call is ignored.");
            }
            return true;
        }

        AgentAttache attache = findAttache(hostId);
        // Get storage pool host mappings here because they can be removed as a part of handleDisconnect later
        List<StoragePoolHostVO> pools = _storagePoolHostDao.listByHostIdIncludingRemoved(hostId);

        try {

            if (host.getType() == Type.Routing) {
                // Check if host is ready for removal
                Status currentState = host.getStatus();
                Status nextState = currentState.getNextStatus(Status.Event.Remove);
                if (nextState == null) {
                    s_logger.debug("There is no transition from state " + currentState + " to state " + Status.Event.Remove);
                    return false;
                }

                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Deleting Host: " + hostId + " Guid:" + host.getGuid());
                }

                if (forceDestroy) {
                    //put local storage into mainenance mode, will set all the VMs on this local storage into stopped state
                    StoragePool storagePool = _storageMgr.findLocalStorageOnHost(host.getId());
                    if (storagePool != null) {
                        if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) {
                            try {
                                storagePool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId());
                                if (storagePool == null) {
                                    s_logger.debug("Failed to set primary storage into maintenance mode");
                                    return false;
                                }
                            } catch (Exception e) {
                                s_logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString());
                                return false;
                            }
                        }
                        List<VMInstanceVO> vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId());
                        for (VMInstanceVO vm : vmsOnLocalStorage) {
                            if(!_vmMgr.destroy(vm, caller, _accountMgr.getAccount(vm.getAccountId()))) {
                                String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + hostId;
                                s_logger.warn(errorMsg);
                                throw new CloudRuntimeException(errorMsg);
                            }
                        }
                    }
                } else {
                    // Check if there are vms running/starting/stopping on this host
                    List<VMInstanceVO> vms = _vmDao.listByHostId(hostId);
                    if (!vms.isEmpty()) {
                        if (isForced) {
                            // Stop HA disabled vms and HA enabled vms in Stopping state
                            // Restart HA enabled vms
                            for (VMInstanceVO vm : vms) {
                                if (!vm.isHaEnabled() || vm.getState() == State.Stopping) {
                                    s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + hostId);
                                    if (!_vmMgr.advanceStop(vm, true, caller, _accountMgr.getAccount(vm.getAccountId()))) {
                                        String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + hostId;
                                        s_logger.warn(errorMsg);
                                        throw new CloudRuntimeException(errorMsg);
                                    }
                                } else if (vm.isHaEnabled() && (vm.getState() == State.Running || vm.getState() == State.Starting)) {
                                    s_logger.debug("Scheduling restart for vm: " + vm + " " + vm.getState() + " on the host id=" + hostId);
                                    _haMgr.scheduleRestart(vm, false);
                                }
                            }
                        } else {
                            throw new CloudRuntimeException("Unable to delete the host as there are vms in " + vms.get(0).getState() + " state using this host and isForced=false specified");
                        }
                    }
                }

                if (host.getHypervisorType() == HypervisorType.XenServer) {
                    if (host.getClusterId() != null) {
                        List<HostVO> hosts = _hostDao.listBy(Type.Routing, host.getClusterId(), host.getPodId(), host.getDataCenterId());
                        hosts.add(host);
                        boolean success = true;
                        for (HostVO thost : hosts) {
                            long thostId = thost.getId();
                            PoolEjectCommand eject = new PoolEjectCommand(host.getGuid());
                            Answer answer = easySend(thostId, eject);
                            if (answer != null && answer.getResult()) {
                                s_logger.debug("Eject Host: " + hostId + " from " + thostId + " Succeed");
                                success = true;
                                break;
                            } else {
                                success = false;
                                s_logger.warn("Eject Host: " + hostId + " from " + thostId + " failed due to " + (answer != null ? answer.getDetails() : "no answer"));
                            }
                        }
                        if (!success) {
                            String msg = "Unable to eject host " + host.getGuid() + " due to there is no host up in this cluster, please execute xe pool-eject host-uuid=" + host.getGuid()
                                    + "in this host " + host.getPrivateIpAddress();
                            s_logger.warn(msg);
                            _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Unable to eject host " + host.getGuid(), msg);
                        }
                    }
                } else if (host.getHypervisorType() == HypervisorType.KVM) {
                    try {
                        ShutdownCommand cmd = new ShutdownCommand(ShutdownCommand.DeleteHost, null);
                        send(host.getId(), cmd);
                    } catch (AgentUnavailableException e) {
                        s_logger.warn("Sending ShutdownCommand failed: ", e);
                    } catch (OperationTimedoutException e) {
                        s_logger.warn("Sending ShutdownCommand failed: ", e);
                    }
                } else if (host.getHypervisorType() == HypervisorType.BareMetal) {
                    List<VMInstanceVO> deadVms = _vmDao.listByLastHostId(hostId);
                    for (VMInstanceVO vm : deadVms) {
                        if (vm.getState() == State.Running || vm.getHostId() != null) {
                            throw new CloudRuntimeException("VM " + vm.getId() + "is still running on host " + hostId);
                        }
                        _vmDao.remove(vm.getId());
                    }
                }
            }

            Transaction txn = Transaction.currentTxn();
            txn.start();

            _dcDao.releasePrivateIpAddress(host.getPrivateIpAddress(), host.getDataCenterId(), null);
            if (attache != null) {
                handleDisconnect(attache, Status.Event.Remove, false);
            }
            // delete host details
            _hostDetailsDao.deleteDetails(hostId);

            host.setGuid(null);
            Long clusterId = host.getClusterId();
            host.setClusterId(null);
            _hostDao.update(host.getId(), host);

            _hostDao.remove(hostId);
            if (clusterId != null) {
                List<HostVO> hosts = _hostDao.listByCluster(clusterId);
                if (hosts.size() == 0) {
                    ClusterVO cluster = _clusterDao.findById(clusterId);
                    cluster.setGuid(null);
                    _clusterDao.update(clusterId, cluster);
                }
            }

            // Delete the associated entries in host ref table
            _storagePoolHostDao.deletePrimaryRecordsForHost(hostId);

            // For pool ids you got, delete local storage host entries in pool table where
            for (StoragePoolHostVO pool : pools) {
                Long poolId = pool.getPoolId();
                StoragePoolVO storagePool = _storagePoolDao.findById(poolId);
                if (storagePool.isLocal() && forceDestroy) {
                    storagePool.setUuid(null);
                    storagePool.setClusterId(null);
                    _storagePoolDao.update(poolId, storagePool);
                    _storagePoolDao.remove(poolId);
                    s_logger.debug("Local storage id=" + poolId + " is removed as a part of host removal id=" + hostId);
                }
            }

            // delete the op_host_capacity entry
            Object[] capacityTypes = { Capacity.CAPACITY_TYPE_CPU, Capacity.CAPACITY_TYPE_MEMORY };
            SearchCriteria<CapacityVO> hostCapacitySC = _capacityDao.createSearchCriteria();
            hostCapacitySC.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId);
            hostCapacitySC.addAnd("capacityType", SearchCriteria.Op.IN, capacityTypes);
            _capacityDao.remove(hostCapacitySC);
            txn.commit();
            return true;
        } catch (Throwable t) {
            s_logger.error("Unable to delete host: " + hostId, t);
            return false;
        }
    }

    @Override
    public boolean updateHostPassword(UpdateHostPasswordCmd upasscmd) {
        if (upasscmd.getClusterId() == null) {
            //update agent attache password
            AgentAttache agent = this.findAttache(upasscmd.getHostId());
            if (!(agent instanceof DirectAgentAttache)) {
                return false;
            }
            UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(upasscmd.getUsername(), upasscmd.getPassword());
            agent.updatePassword(cmd);
        }
        else {
            // get agents for the cluster
            List<HostVO> hosts = _hostDao.listByCluster(upasscmd.getClusterId());
            for (HostVO h : hosts) {
                AgentAttache agent = this.findAttache(h.getId());
                if (!(agent instanceof DirectAgentAttache)) {
                    continue;
                }
                UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(upasscmd.getUsername(), upasscmd.getPassword());
                agent.updatePassword(cmd);
            }
        }
        return true;
    }

    protected int getPingInterval() {
        return _pingInterval;
    }

    @Override
    public Answer send(Long hostId, Command cmd) throws AgentUnavailableException, OperationTimedoutException {
        Commands cmds = new Commands(OnError.Stop);
        cmds.addCommand(cmd);
        send(hostId, cmds, cmd.getWait());
        Answer[] answers = cmds.getAnswers();
        if (answers != null && !(answers[0] instanceof UnsupportedAnswer)) {
            return answers[0];
        }

        if (answers != null && (answers[0] instanceof UnsupportedAnswer)) {
            s_logger.warn("Unsupported Command: " + answers[0].getDetails());
            return answers[0];
        }

        return null;
    }

    @DB
    protected boolean noDbTxn() {
        Transaction txn = Transaction.currentTxn();
        return !txn.dbTxnStarted();
    }

    @Override
    public Answer[] send(Long hostId, Commands commands, int timeout) throws AgentUnavailableException, OperationTimedoutException {
        assert hostId != null : "Who's not checking the agent id before sending?  ... (finger wagging)";
        if (hostId == null) {
            throw new AgentUnavailableException(-1);
        }

        assert noDbTxn() : "I know, I know.  Why are we so strict as to not allow txn across an agent call?  ...  Why are we so cruel ... Why are we such a dictator .... Too bad... Sorry...but NO AGENT COMMANDS WRAPPED WITHIN DB TRANSACTIONS!";

        Command[] cmds = commands.toCommands();

        assert cmds.length > 0 : "Ask yourself this about a hundred times.  Why am I  sending zero length commands?";

        if (cmds.length == 0) {
            commands.setAnswers(new Answer[0]);
        }

        final AgentAttache agent = getAttache(hostId);
        if (agent == null || agent.isClosed()) {
            throw new AgentUnavailableException("agent not logged into this management server", hostId);
        }

        Request req = new Request(hostId, _nodeId, cmds, commands.stopOnError(), true);
        req.setSequence(agent.getNextSequence());
        Answer[] answers = agent.send(req, timeout);
        notifyAnswersToMonitors(hostId, req.getSequence(), answers);
        commands.setAnswers(answers);
        return answers;
    }

    protected Status investigate(AgentAttache agent) {
        Long hostId = agent.getId();
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("checking if agent (" + hostId + ") is alive");
        }

        Answer answer = easySend(hostId, new CheckHealthCommand());
        if (answer != null && answer.getResult()) {
            Status status = Status.Up;
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("agent (" + hostId + ") responded to checkHeathCommand, reporting that agent is " + status);
            }
            return status;
        }

        return _haMgr.investigate(hostId);
    }

    protected AgentAttache getAttache(final Long hostId) throws AgentUnavailableException {
        assert (hostId != null) : "Who didn't check their id value?";
        if (hostId == null) {
            return null;
        }
        AgentAttache agent = findAttache(hostId);
        if (agent == null) {
            s_logger.debug("Unable to find agent for " + hostId);
            throw new AgentUnavailableException("Unable to find agent ", hostId);
        }

        return agent;
    }

    @Override
    public long send(Long hostId, Commands commands, Listener listener) throws AgentUnavailableException {
        final AgentAttache agent = getAttache(hostId);
        if (agent.isClosed()) {
            return -1;
        }

        Command[] cmds = commands.toCommands();

        assert cmds.length > 0 : "Why are you sending zero length commands?";
        if (cmds.length == 0) {
            return -1;
        }
        Request req = new Request(hostId, _nodeId, cmds, commands.stopOnError(), true);
        req.setSequence(agent.getNextSequence());
        agent.send(req, listener);
        return req.getSequence();
    }




    @Override
    public long gatherStats(Long hostId, Command cmd, Listener listener) {
        try {
            return send(hostId, new Commands(cmd), listener);
        } catch (final AgentUnavailableException e) {
            return -1;
        }
    }

    public void removeAgent(AgentAttache attache, Status nextState) {
        if (attache == null) {
            return;
        }
        long hostId = attache.getId();
        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Remove Agent : " + hostId);
        }
        AgentAttache removed = null;
        boolean conflict = false;
        synchronized (_agents) {
            removed = _agents.remove(hostId);
            if (removed != null && removed != attache) {
                conflict = true;
                _agents.put(hostId, removed);
                removed = attache;
            }
        }
        if (conflict) {
            s_logger.debug("Agent for host " + hostId + " is created when it is being disconnected");
        }
        if (removed != null) {
            removed.disconnect(nextState);
        }
    }

    @Override
    public void disconnect(final long hostId, final Status.Event event, final boolean investigate) {
        AgentAttache attache = findAttache(hostId);

        if (attache != null) {
            disconnect(attache, event, investigate);
        } else {
            synchronized (_loadingAgents) {
                if (_loadingAgents.contains(hostId)) {
                    s_logger.info("Host " + hostId + " is being loaded so no disconnects needed.");
                    return;
                }
            }

            HostVO host = _hostDao.findById(hostId);
            if (host != null && host.getRemoved() == null) {
                if (event != null && event.equals(Event.Remove)) {
                    host.setGuid(null);
                    host.setClusterId(null);
                }
                _hostDao.updateStatus(host, event, _nodeId);
            }
        }
    }
    
    @Override
    public boolean disconnect(final long hostId) {
        disconnect(hostId, Event.PrepareUnmanaged, false);
        return true;
    }

    @Override
    public void updateStatus(HostVO host, Status.Event event) {
        _hostDao.updateStatus(host, event, _nodeId);
    }
    public void disconnect(AgentAttache attache, final Status.Event event, final boolean investigate) {
        _executor.submit(new DisconnectTask(attache, event, investigate));
    }

    protected boolean handleDisconnect(AgentAttache attache, Status.Event event, boolean investigate) {
        if (attache == null) {
            return true;
        }

        long hostId = attache.getId();

        s_logger.info("Host " + hostId + " is disconnecting with event " + event);

        HostVO host = _hostDao.findById(hostId);
        if (host == null) {
            s_logger.warn("Can't find host with " + hostId);
            removeAgent(attache, Status.Removed);
            return true;

        }
        final Status currentState = host.getStatus();
        if (currentState == Status.Down || currentState == Status.Alert || currentState == Status.Removed) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Host " + hostId + " is already " + currentState);
            }
            if (currentState != Status.PrepareForMaintenance) {
                removeAgent(attache, currentState);
            }
            return true;
        }
        Status nextState = currentState.getNextStatus(event);
        if (nextState == null) {
            if (!(attache instanceof DirectAgentAttache)) {
                return false;
            }

            s_logger.debug("There is no transition from state " + currentState + " and event " + event);
            assert false : "How did we get here.  Look at the FSM";
            return false;
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("The next state is " + nextState + ", current state is " + currentState);
        }

        // Now we go and correctly diagnose what the actual situation is
        if (nextState == Status.Alert && investigate) {
            s_logger.info("Investigating why host " + hostId + " has disconnected with event " + event);

            final Status determinedState = investigate(attache);
            s_logger.info("The state determined is " + determinedState);

            if (determinedState == null || determinedState == Status.Down) {
                s_logger.error("Host is down: " + host.getId() + "-" + host.getName() + ".  Starting HA on the VMs");

                event = Event.HostDown;
            } else if (determinedState == Status.Up) {
                // we effectively pinged from the server here.
                s_logger.info("Agent is determined to be up and running");
                _monitor.pingBy(host.getId());
                // _hostDao.updateStatus(host, Event.Ping, _nodeId);
                return false;
            } else if (determinedState == Status.Disconnected) {
                s_logger.warn("Agent is disconnected but the host is still up: " + host.getId() + "-" + host.getName());
                if (currentState == Status.Disconnected) {
                    Long hostPingTime = _monitor.getAgentPingTime(host.getId());
                    if (hostPingTime == null) {
                        s_logger.error("Host is not on this management server any more: " + host);
                        return false;
                    }
                    if ((InaccurateClock.getTimeInSeconds() - hostPingTime) > _alertWait) {
                        s_logger.warn("Host " + host.getId() + " has been disconnected pass the time it should be disconnected.");
                        event = Event.WaitedTooLong;
                    } else {
                        s_logger.debug("Host has been determined to be disconnected but it hasn't passed the wait time yet.");
                        return false;
                    }
                } else if (currentState == Status.Updating) {
                    Long hostPingTime = _monitor.getAgentPingTime(host.getId());
                    if (hostPingTime == null) {
                        s_logger.error("Host is not on this management server any more: " + host);
                        return false;
                    }
                    if ((InaccurateClock.getTimeInSeconds() - hostPingTime) > _updateWait) {
                        s_logger.warn("Host " + host.getId() + " has been updating for too long");

                        event = Event.WaitedTooLong;
                    } else {
                        s_logger.debug("Host has been determined to be disconnected but it hasn't passed the wait time yet.");
                        return false;
                    }
                } else if (currentState == Status.Up) {
                    DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId());
                    HostPodVO podVO = _podDao.findById(host.getPodId());
                    String hostDesc = "name: " + host.getName() + " (id:" + host.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName();
                    if ((host.getType() != Host.Type.SecondaryStorage) && (host.getType() != Host.Type.ConsoleProxy)) {
                        _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Host disconnected, " + hostDesc, "If the agent for host [" + hostDesc
                                + "] is not restarted within " + _alertWait + " seconds, HA will begin on the VMs");
                    }
                    event = Event.AgentDisconnected;
                }
            } else {
                // if we end up here we are in alert state, send an alert
                DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId());
                HostPodVO podVO = _podDao.findById(host.getPodId());
                String hostDesc = "name: " + host.getName() + " (id:" + host.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName();
                _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Host in ALERT state, " + hostDesc, "In availability zone " + host.getDataCenterId()
                        + ", host is in alert state: " + host.getId() + "-" + host.getName());
            }
        }

        if (s_logger.isDebugEnabled()) {
            s_logger.debug("Deregistering link for " + hostId + " with state " + nextState);
        }
        removeAgent(attache, nextState);
        _hostDao.disconnect(host, event, _nodeId);

        host = _hostDao.findById(host.getId());
        if (!event.equals(Event.PrepareUnmanaged) && !event.equals(Event.HypervisorVersionChanged) && (host.getStatus() == Status.Alert || host.getStatus() == Status.Down)) {
            _haMgr.scheduleRestartForVmsOnHost(host, investigate);
        }

        for (Pair<Integer, Listener> monitor : _hostMonitors) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Sending Disconnect to listener: " + monitor.second().getClass().getName());
            }
            monitor.second().processDisconnect(hostId, nextState);
        }

        return true;
    }

    protected AgentAttache notifyMonitorsOfConnection(AgentAttache attache, final StartupCommand[] cmd, boolean forRebalance) throws ConnectionException {
        long hostId = attache.getId();
        HostVO host = _hostDao.findById(hostId);
        for (Pair<Integer, Listener> monitor : _hostMonitors) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Sending Connect to listener: " + monitor.second().getClass().getSimpleName());
            }
            for (int i = 0; i < cmd.length; i++) {
                try {
                    monitor.second().processConnect(host, cmd[i], forRebalance);
                } catch (Exception e) {
                    if (e instanceof ConnectionException) {
                        ConnectionException ce = (ConnectionException)e;
                        if (ce.isSetupError()) {
                            s_logger.warn("Monitor " + monitor.second().getClass().getSimpleName() + " says there is an error in the connect process for " + hostId + " due to " + e.getMessage());
                            handleDisconnect(attache, Event.AgentDisconnected, false);
                            throw ce;
                        } else {
                            s_logger.info("Monitor " + monitor.second().getClass().getSimpleName() + " says not to continue the connect process for " + hostId + " due to " + e.getMessage());
                            handleDisconnect(attache, Event.ShutdownRequested, false);
                            return attache;
                        }
                    } else if (e instanceof HypervisorVersionChangedException) {
                        handleDisconnect(attache, Event.HypervisorVersionChanged, false);
                        throw new CloudRuntimeException("Unable to connect " + attache.getId(), e);
                    } else {
                        s_logger.error("Monitor " + monitor.second().getClass().getSimpleName() + " says there is an error in the connect process for " + hostId + " due to " + e.getMessage(), e);
                        handleDisconnect(attache, Event.AgentDisconnected, false);
                        throw new CloudRuntimeException("Unable to connect " + attache.getId(), e);
                    }
                }
            }
        }

        Long dcId = host.getDataCenterId();
        ReadyCommand ready = new ReadyCommand(dcId);
        Answer answer = easySend(hostId, ready);
        if (answer == null || !answer.getResult()) {
            // this is tricky part for secondary storage
            // make it as disconnected, wait for secondary storage VM to be up
            // return the attache instead of null, even it is disconnectede
            handleDisconnect(attache, Event.AgentDisconnected, false);
        }

        _hostDao.updateStatus(host, Event.Ready, _nodeId);
        attache.ready();
        return attache;
    }

    protected boolean notifyCreatorsOfConnection(StartupCommand[] cmd) throws ConnectionException {
        boolean handled = false;
        for (Pair<Integer, StartupCommandProcessor> monitor : _creationMonitors) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Sending Connect to creator: "
                        + monitor.second().getClass().getSimpleName());
            }
            handled =  monitor.second().processInitialConnect(cmd);
            if (handled) {
                break;
            }
        }

        return handled;
    }

    @Override
    public boolean start() {
        startDirectlyConnectedHosts();
        if (_monitor != null) {
            _monitor.start();
        }
        if (_connection != null) {
            _connection.start();
        }

        return true;
    }

    public void startDirectlyConnectedHosts() {
        List<HostVO> hosts = _hostDao.findDirectlyConnectedHosts();
        for (HostVO host : hosts) {
            loadDirectlyConnectedHost(host, false);
        }
    }

    @SuppressWarnings("rawtypes")
    protected boolean loadDirectlyConnectedHost(HostVO host, boolean forRebalance) {
    	boolean initialized = false;
        ServerResource resource = null;
    	try {
	        String resourceName = host.getResource();
	        try {
	            Class<?> clazz = Class.forName(resourceName);
	            Constructor constructor = clazz.getConstructor();
	            resource = (ServerResource) constructor.newInstance();
	        } catch (ClassNotFoundException e) {
	            s_logger.warn("Unable to find class " + host.getResource(), e);
	            return false;
	        } catch (InstantiationException e) {
	            s_logger.warn("Unablet to instantiate class " + host.getResource(), e);
	            return false;
	        } catch (IllegalAccessException e) {
	            s_logger.warn("Illegal access " + host.getResource(), e);
	            return false;
	        } catch (SecurityException e) {
	            s_logger.warn("Security error on " + host.getResource(), e);
	            return false;
	        } catch (NoSuchMethodException e) {
	            s_logger.warn("NoSuchMethodException error on " + host.getResource(), e);
	            return false;
	        } catch (IllegalArgumentException e) {
	            s_logger.warn("IllegalArgumentException error on " + host.getResource(), e);
	            return false;
	        } catch (InvocationTargetException e) {
	            s_logger.warn("InvocationTargetException error on " + host.getResource(), e);
	            return false;
	        }
	
	        _hostDao.loadDetails(host);
	
	        HashMap<String, Object> params = new HashMap<String, Object>(host.getDetails().size() + 5);
	        params.putAll(host.getDetails());
	
	        params.put("guid", host.getGuid());
	        params.put("zone", Long.toString(host.getDataCenterId()));
	        if (host.getPodId() != null) {
	            params.put("pod", Long.toString(host.getPodId()));
	        }
	        if (host.getClusterId() != null) {
	            params.put("cluster", Long.toString(host.getClusterId()));
	            String guid = null;
	            ClusterVO cluster = _clusterDao.findById(host.getClusterId());
	            if (cluster.getGuid() == null) {
	                guid = host.getDetail("pool");
	            } else {
	                guid = cluster.getGuid();
	            }
	            if (guid != null && !guid.isEmpty()) {
	                params.put("pool", guid);
	            }
	        }
	
	        params.put("ipaddress", host.getPrivateIpAddress());
	        params.put("secondary.storage.vm", "false");
	        params.put("max.template.iso.size", _configDao.getValue(Config.MaxTemplateAndIsoSize.toString()));
	        params.put("migratewait", _configDao.getValue(Config.MigrateWait.toString()));
	
	        try {
	            resource.configure(host.getName(), params);
	        } catch (ConfigurationException e) {
	            s_logger.warn("Unable to configure resource due to ", e);
	            return false;
	        }
	
	        if (!resource.start()) {
	            s_logger.warn("Unable to start the resource");
	            return false;
	        }
        
	        initialized = true;
    	} finally {
    		if(!initialized) {
                if (host != null) {
                    _hostDao.updateStatus(host, Event.AgentDisconnected, _nodeId);
                }
    		}	
    	}

        if (forRebalance) {
            AgentAttache attache = simulateStart(host.getId(), resource, host.getDetails(), false, null, null, true);
            if (attache == null) {
                return false;
            } else {
                return true;
            }
        } else {
            _executor.execute(new SimulateStartTask(host.getId(), resource, host.getDetails(), null));
            return true;
        }
    }

    @Override
    public AgentAttache simulateStart(Long id, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags, String allocationState, boolean forRebalance) throws IllegalArgumentException {
        HostVO host = null;
        if (id != null) {
            synchronized (_loadingAgents) {
                s_logger.debug("Adding to loading agents " + id);
                _loadingAgents.add(id);
            }
        }
        AgentAttache attache = null;
        StartupCommand[] cmds = null;
        try {
            if (id != null) {
                host = _hostDao.findById(id);
                if (!_hostDao.directConnect(host, _nodeId)) {
                    s_logger.info("MS " + host.getManagementServerId() + " is loading " + host);
                    return null;
                }
            }

            cmds = resource.initialize();
            if (cmds == null) {
                s_logger.info("Unable to fully initialize the agent because no StartupCommands are returned");
                return null;
            }

            if (host != null) {
                if (!_hostDao.directConnect(host, _nodeId)) {
                    host = _hostDao.findById(id);
                    s_logger.info("MS " + host.getManagementServerId() + " is loading " + host + " after it has been initialized.");
                    return null;
                }
            }

            if (s_logger.isDebugEnabled()) {
                new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true);
            }
            try {
                attache = handleDirectConnect(resource, cmds, details, old, hostTags, allocationState, forRebalance);
            } catch (IllegalArgumentException ex) {
                s_logger.warn("Unable to connect due to ", ex);
                throw ex;
            } catch (Exception e) {
                s_logger.warn("Unable to connect due to ", e);
            }

        } finally {
            if (id != null) {
                synchronized (_loadingAgents) {
                    _loadingAgents.remove(id);
                }
            }
            if (attache == null) {
                if (cmds != null) {
                    resource.disconnected();
                }
                if (host != null) {
                    _hostDao.updateStatus(host, Event.AgentDisconnected, _nodeId);
                }
            }
        }
        return attache;
    }

    @Override
    public boolean stop() {
        if (_monitor != null) {
            _monitor.signalStop();
        }
        if (_connection != null) {
            _connection.stop();
        }

        s_logger.info("Disconnecting agents: " + _agents.size());
        synchronized (_agents) {
            for (final AgentAttache agent : _agents.values()) {
                final HostVO host = _hostDao.findById(agent.getId());
                if (host == null) {
                    if (s_logger.isDebugEnabled()) {
                        s_logger.debug("Cant not find host " + agent.getId());
                    }
                } else {
                    _hostDao.updateStatus(host, Event.ManagementServerDown, _nodeId);
                }
            }
        }
        return true;
    }

    @Override
    public Pair<HostPodVO, Long> findPod(final VirtualMachineTemplate template, ServiceOfferingVO offering, final DataCenterVO dc, final long accountId, Set<Long> avoids) {
        final Enumeration en = _podAllocators.enumeration();
        while (en.hasMoreElements()) {
            final PodAllocator allocator = (PodAllocator) en.nextElement();
            final Pair<HostPodVO, Long> pod = allocator.allocateTo(template, offering, dc, accountId, avoids);
            if (pod != null) {
                return pod;
            }
        }
        return null;
    }

    @Override
    public HostStats getHostStatistics(long hostId) {
        Answer answer = easySend(hostId, new GetHostStatsCommand(_hostDao.findById(hostId).getGuid(), _hostDao.findById(hostId).getName(), hostId));

        if (answer != null && (answer instanceof UnsupportedAnswer)) {
            return null;
        }

        if (answer == null || !answer.getResult()) {
            String msg = "Unable to obtain host " + hostId + " statistics. ";
            s_logger.warn(msg);
            return null;
        } else {

            // now construct the result object
            if (answer instanceof GetHostStatsAnswer) {
                return ((GetHostStatsAnswer) answer).getHostStats();
            }
        }
        return null;
    }

    @Override
    public Long getGuestOSCategoryId(long hostId) {
        HostVO host = _hostDao.findById(hostId);
        if (host == null) {
            return null;
        } else {
            _hostDao.loadDetails(host);
            DetailVO detail = _hostDetailsDao.findDetail(hostId, "guest.os.category.id");
            if (detail == null) {
                return null;
            } else {
                return Long.parseLong(detail.getValue());
            }
        }
    }

    @Override
    public String getHostTags(long hostId) {
        List<String> hostTags = _hostTagsDao.gethostTags(hostId);
        if (hostTags == null) {
            return null;
        } else {
            return StringUtils.listToCsvTags(hostTags);
        }
    }

    @Override
    public String getName() {
        return _name;
    }

    protected class DisconnectTask implements Runnable {
        AgentAttache _attache;
        Status.Event _event;
        boolean _investigate;

        DisconnectTask(final AgentAttache attache, final Status.Event event, final boolean investigate) {
            _attache = attache;
            _event = event;
            _investigate = investigate;
        }

        @Override
        public void run() {
            try {
                handleDisconnect(_attache, _event, _investigate);
            } catch (final Exception e) {
                s_logger.error("Exception caught while handling disconnect: ", e);
            } finally {
                StackMaid.current().exitCleanup();
            }
        }
    }

    @Override
    public Answer easySend(final Long hostId, final Command cmd) {
        try {
            Host h = _hostDao.findById(hostId);
            if (h == null || h.getRemoved() != null) {
                s_logger.debug("Host with id " + hostId + " doesn't exist");
                return null;
            }
            Status status = h.getStatus();
            if (!status.equals(Status.Up) && !status.equals(Status.Connecting)) {
                return null;
            }
            final Answer answer = send(hostId, cmd);
            if (answer == null) {
                s_logger.warn("send returns null answer");
                return null;
            }

            if (s_logger.isDebugEnabled() && answer.getDetails() != null) {
                s_logger.debug("Details from executing " + cmd.getClass() + ": " + answer.getDetails());
            }

            return answer;

        } catch (final AgentUnavailableException e) {
            s_logger.warn(e.getMessage());
            return null;
        } catch (final OperationTimedoutException e) {
            s_logger.warn("Operation timed out: " + e.getMessage());
            return null;
        } catch (final Exception e) {
            s_logger.warn("Exception while sending", e);
            return null;
        }
    }

    @Override
    public Answer[] send(final Long hostId, Commands cmds) throws AgentUnavailableException, OperationTimedoutException {
        int wait = 0;
        for( Command cmd : cmds ) {
            if ( cmd.getWait() > wait ) {
                wait = cmd.getWait();
            }
        }
        if ( wait == 0 ) {
            wait = _wait;
        }
        return send(hostId, cmds, wait);
    }

    @Override
    public boolean reconnect(final long hostId) throws AgentUnavailableException {
        HostVO host;

        host = _hostDao.findById(hostId);
        if (host == null || host.getRemoved() != null) {
            s_logger.warn("Unable to find host " + hostId);
            return false;
        }

        if (host.getStatus() != Status.Up && host.getStatus() != Status.Alert) {
            s_logger.info("Unable to disconnect host because it is not in the correct state: host=" + hostId + "; Status=" + host.getStatus());
            return false;
        }

        AgentAttache attache = findAttache(hostId);
        if (attache == null) {
            s_logger.info("Unable to disconnect host because it is not connected to this server: " + hostId);
            return false;
        }

        disconnect(attache, Event.ShutdownRequested, false);
        return true;
    }

    @Override
    public boolean cancelMaintenance(final long hostId) {

        HostVO host;
        host = _hostDao.findById(hostId);
        if (host == null || host.getRemoved() != null) {
            s_logger.warn("Unable to find host " + hostId);
            return true;
        }

        if (host.getStatus() != Status.PrepareForMaintenance && host.getStatus() != Status.Maintenance && host.getStatus() != Status.ErrorInMaintenance) {
            return true;
        }

        _haMgr.cancelScheduledMigrations(host);
        List<VMInstanceVO> vms = _haMgr.findTakenMigrationWork();
        for (VMInstanceVO vm : vms) {
            if (vm.getHostId() != null && vm.getHostId() == hostId) {
                s_logger.info("Unable to cancel migration because the vm is being migrated: " + vm);
                return false;
            }
        }
        disconnect(hostId, Event.ResetRequested, false);
        return true;
    }

    @Override
    public boolean executeUserRequest(long hostId, Event event) throws AgentUnavailableException {
        if (event == Event.MaintenanceRequested) {
            return maintain(hostId);
        } else if (event == Event.ResetRequested) {
            return cancelMaintenance(hostId);
        } else if (event == Event.PrepareUnmanaged) {
            return disconnect(hostId);
        } else if (event == Event.Remove) {
            User caller = _accountMgr.getActiveUser(User.UID_SYSTEM);
            return deleteHost(hostId, false, false, caller);
        } else if (event == Event.AgentDisconnected) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Received agent disconnect event for host " + hostId);
            }
            AgentAttache attache = null;
            attache = findAttache(hostId);
            if (attache != null) {
                handleDisconnect(attache, Event.AgentDisconnected, false);
            }
            return true;
        } else if (event == Event.ShutdownRequested) {
            return reconnect(hostId);
        }
        else if (event == Event.UpdatePassword) {
            AgentAttache attache = findAttache(hostId);
            if (attache != null) {
                DetailVO nv = _detailsDao.findDetail(hostId, ApiConstants.USERNAME);
                String username = nv.getValue();
                nv = _detailsDao.findDetail(hostId, ApiConstants.PASSWORD);
                String password = nv.getValue();
                UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(username, password);
                attache.updatePassword(cmd);
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean maintain(final long hostId) throws AgentUnavailableException {
        HostVO host = _hostDao.findById(hostId);
        Status state;

        MaintainAnswer answer = (MaintainAnswer) easySend(hostId, new MaintainCommand());
        if (answer == null || !answer.getResult()) {
            s_logger.warn("Unable to put host in maintainance mode: " + hostId);
            return false;
        }

        // Let's put this guy in maintenance state
        do {
            host = _hostDao.findById(hostId);
            if (host == null) {
                s_logger.debug("Unable to find host " + hostId);
                return false;
            }
            state = host.getStatus();
            if (state == Status.Disconnected || state == Status.Updating) {
                s_logger.debug("Unable to put host " + hostId + " in matinenance mode because it is currently in " + state);
                throw new AgentUnavailableException("Agent is in " + state + " state.  Please wait for it to become Alert state try again.", hostId);
            }
        } while (!_hostDao.updateStatus(host, Event.MaintenanceRequested, _nodeId));

        AgentAttache attache = findAttache(hostId);
        if (attache != null) {
            attache.setMaintenanceMode(true);
        }

        if (attache != null) {
            // Now cancel all of the commands except for the active one.
            attache.cancelAllCommands(Status.PrepareForMaintenance, false);
        }

        final Host.Type type = host.getType();

        if (type == Host.Type.Routing) {

            final List<VMInstanceVO> vms = _vmDao.listByHostId(hostId);
            if (vms.size() == 0) {
                return true;
            }

            List<HostVO> hosts = _hostDao.listBy(host.getClusterId(), host.getPodId(), host.getDataCenterId());
            List<Long> upHosts = _hostDao.listBy( host.getDataCenterId(), host.getPodId(), host.getClusterId(), Host.Type.Routing, Status.Up);
            for (final VMInstanceVO vm : vms) {
                if (hosts == null || hosts.size() <= 1 || !answer.getMigrate() || upHosts == null || upHosts.size() == 0) {
                    // for the last valid host in this cluster, stop all the VMs
                    _haMgr.scheduleStop(vm, hostId, WorkType.ForceStop);
                } else {
                    _haMgr.scheduleMigration(vm);
                }
            }
        }

        return true;
    }


    public boolean checkCIDR(Host.Type type, HostPodVO pod, String serverPrivateIP, String serverPrivateNetmask) {
        if (serverPrivateIP == null) {
            return true;
        }
        // Get the CIDR address and CIDR size
        String cidrAddress = pod.getCidrAddress();
        long cidrSize = pod.getCidrSize();

        // If the server's private IP address is not in the same subnet as the
        // pod's CIDR, return false
        String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize);
        String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask);
        if (!cidrSubnet.equals(serverSubnet)) {
            return false;
        }

        // If the server's private netmask is less inclusive than the pod's CIDR
        // netmask, return false
        String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize);
        long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask);
        long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask);
        if (serverNetmaskNumeric > cidrNetmaskNumeric) {
            return false;
        }
        return true;
    }

    protected void checkCIDR(Host.Type type, HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask) throws IllegalArgumentException {
        // Skip this check for Storage Agents and Console Proxies
        if (type == Host.Type.Storage || type == Host.Type.ConsoleProxy) {
            return;
        }

        if (serverPrivateIP == null) {
            return;
        }
        // Get the CIDR address and CIDR size
        String cidrAddress = pod.getCidrAddress();
        long cidrSize = pod.getCidrSize();

        // If the server's private IP address is not in the same subnet as the
        // pod's CIDR, return false
        String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize);
        String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask);
        if (!cidrSubnet.equals(serverSubnet)) {
            s_logger.warn("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName() + " and zone: " + dc.getName());
            throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName() + " and zone: " + dc.getName());
        }

        // If the server's private netmask is less inclusive than the pod's CIDR
        // netmask, return false
        String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize);
        long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask);
        long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask);
        if (serverNetmaskNumeric > cidrNetmaskNumeric) {
            throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName() + " and zone: " + dc.getName());
        }

    }

    public void checkIPConflicts(Host.Type type, HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask, String serverPublicIP, String serverPublicNetmask) {
        // If the server's private IP is the same as is public IP, this host has
        // a host-only private network. Don't check for conflicts with the
        // private IP address table.
        if (serverPrivateIP != serverPublicIP) {
            if (!_privateIPAddressDao.mark(dc.getId(), pod.getId(), serverPrivateIP)) {
                // If the server's private IP address is already in the
                // database, return false
                List<DataCenterIpAddressVO> existingPrivateIPs = _privateIPAddressDao.listByPodIdDcIdIpAddress(pod.getId(), dc.getId(), serverPrivateIP);

                assert existingPrivateIPs.size() <= 1 : " How can we get more than one ip address with " + serverPrivateIP;
                if (existingPrivateIPs.size() > 1) {
                    throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is already in use in pod: " + pod.getName() + " and zone: " + dc.getName());
                }
                if (existingPrivateIPs.size() == 1) {
                    DataCenterIpAddressVO vo = existingPrivateIPs.get(0);
                    if (vo.getInstanceId() != null) {
                        throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is already in use in pod: " + pod.getName() + " and zone: " + dc.getName());
                    }
                }
            }
        }

        if (serverPublicIP != null && !_publicIPAddressDao.mark(dc.getId(), new Ip(serverPublicIP))) {
            // If the server's public IP address is already in the database,
            // return false
            List<IPAddressVO> existingPublicIPs = _publicIPAddressDao.listByDcIdIpAddress(dc.getId(), serverPublicIP);
            if (existingPublicIPs.size() > 0) {
                throw new IllegalArgumentException("The public ip address of the server (" + serverPublicIP + ") is already in use in zone: " + dc.getName());
            }
        }
    }

    @Override
    public Host addHost(long zoneId, ServerResource resource, Type hostType, Map<String, String> hostDetails) {
        // Check if the zone exists in the system
        if (_dcDao.findById(zoneId) == null) {
            throw new InvalidParameterValueException("Can't find zone with id " + zoneId);
        }

        Map<String, String> details = hostDetails;
        String guid = details.get("guid");
        List<HostVO> currentHosts = _hostDao.listBy(hostType, zoneId);
        for (HostVO currentHost : currentHosts) {
            if (currentHost.getGuid().equals(guid)) {
                return currentHost;
            }
        }

        AgentAttache attache = simulateStart(null, resource, hostDetails, true, null, null, false);
        return _hostDao.findById(attache.getId());
    }

    public HostVO createHost(final StartupCommand startup, ServerResource resource, Map<String, String> details, boolean directFirst, List<String> hostTags, String allocationState)
            throws IllegalArgumentException {
        Host.Type type = null;

        if (startup instanceof StartupStorageCommand) {
            StartupStorageCommand ssCmd = ((StartupStorageCommand) startup);
            if (ssCmd.getHostType() == Host.Type.SecondaryStorageCmdExecutor) {
                type = ssCmd.getHostType();
            } else {
                if (ssCmd.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE) {
                    type = Host.Type.SecondaryStorage;
                    if (resource != null && resource instanceof DummySecondaryStorageResource) {
                        resource = null;
                    }
                }else if (ssCmd.getResourceType() == Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE) {
                    type = Host.Type.LocalSecondaryStorage;

                } else {
                    type = Host.Type.Storage;
                }

                final Map<String, String> hostDetails = ssCmd.getHostDetails();
                if (hostDetails != null) {
                    if (details != null) {
                        details.putAll(hostDetails);
                    } else {
                        details = hostDetails;
                    }
                }
            }
        } else if (startup instanceof StartupRoutingCommand) {
            StartupRoutingCommand ssCmd = ((StartupRoutingCommand) startup);
            type = Host.Type.Routing;
            final Map<String, String> hostDetails = ssCmd.getHostDetails();
            if (hostDetails != null) {
                if (details != null) {
                    details.putAll(hostDetails);
                } else {
                    details = hostDetails;
                }
            }
        } else if (startup instanceof StartupSecondaryStorageCommand) {
            type = Host.Type.SecondaryStorageVM;
        } else if (startup instanceof StartupProxyCommand) {
            type = Host.Type.ConsoleProxy;
        } else if (startup instanceof StartupExternalFirewallCommand) {
            type = Host.Type.ExternalFirewall;
        } else if (startup instanceof StartupExternalLoadBalancerCommand) {
            type = Host.Type.ExternalLoadBalancer;
        } else if (startup instanceof StartupPxeServerCommand) {
            type = Host.Type.PxeServer;
        } else if (startup instanceof StartupExternalDhcpCommand) {
            type = Host.Type.ExternalDhcp;
        } else if (startup instanceof StartupTrafficMonitorCommand) {
            type = Host.Type.TrafficMonitor;
        } else {
            assert false : "Did someone add a new Startup command?";
        }

        Long id = null;
        HostVO server = _hostDao.findByGuid(startup.getGuid());
        if (server == null) {
            server = _hostDao.findByGuid(startup.getGuidWithoutResource());
        }
        if (server != null && server.getRemoved() == null) {
            id = server.getId();
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Found the host " + id + " by guid: " + startup.getGuid());
            }
            if (directFirst) {
                s_logger.debug("Old host reconnected as new");
                return null;
            }
        } else {
            server = new HostVO(startup.getGuid());
        }

        server.setDetails(details);
        server.setHostTags(hostTags);

        if (allocationState != null) {
            try {
                HostAllocationState hostAllocationState = Host.HostAllocationState.valueOf(allocationState);
                if (hostAllocationState != null) {
                    server.setHostAllocationState(hostAllocationState);
                }
            } catch (IllegalArgumentException ex) {
                s_logger.error("Unable to resolve " + allocationState + " to a valid supported host allocation State, defaulting to 'Enabled'");
                server.setHostAllocationState(Host.HostAllocationState.Enabled);
            }
        } else {
            server.setHostAllocationState(Host.HostAllocationState.Enabled);
        }

        updateHost(server, startup, type, _nodeId);
        if (resource != null) {
            server.setResource(resource.getClass().getName());
        }
        if (id == null) {
            /*
             * // ignore integrity check for agent-simulator if(!"0.0.0.0".equals(startup.getPrivateIpAddress()) &&
             * !"0.0.0.0".equals(startup.getStorageIpAddress())) { if (_hostDao.findByPrivateIpAddressInDataCenter
             * (server.getDataCenterId(), startup.getPrivateIpAddress()) != null) { throw newIllegalArgumentException(
             * "The private ip address is already in used: " + startup.getPrivateIpAddress()); }
             *
             * if (_hostDao.findByPrivateIpAddressInDataCenter(server.getDataCenterId (), startup.getStorageIpAddress()) !=
             * null) { throw new IllegalArgumentException ("The private ip address is already in used: " +
             * startup.getStorageIpAddress()); } }
             */

            if (startup instanceof StartupProxyCommand) {
                server.setProxyPort(((StartupProxyCommand) startup).getProxyPort());
            }

            server = _hostDao.persist(server);
            id = server.getId();

            s_logger.info("New " + server.getType() + " host connected w/ guid " + startup.getGuid() + " and id is " + id);
        } else {
            if (!_hostDao.connect(server, _nodeId)) {
                throw new CloudRuntimeException("Agent cannot connect because the current state is " + server.getStatus());
            }
            s_logger.info("Old " + server.getType() + " host reconnected w/ id =" + id);
        }

        return server;
    }

    public HostVO createHost(final StartupCommand[] startup, ServerResource resource, Map<String, String> details, boolean directFirst, List<String> hostTags, String allocationState)
            throws IllegalArgumentException {
        StartupCommand firstCmd = startup[0];
        HostVO result = createHost(firstCmd, resource, details, directFirst, hostTags, allocationState);
        if (result == null) {
            return null;
        }
        return result;
    }

    public AgentAttache handleConnect(final Link link,
            final StartupCommand[] startup) throws IllegalArgumentException,
            ConnectionException {
        HostVO server = null;
        boolean handled = notifyCreatorsOfConnection(startup);
        if (!handled) {
            server = createHost(startup, null, null, false, null, null);
        } else {
            server = _hostDao.findByGuid(startup[0].getGuid());
        }

        if (server == null) {
            return null;
        }
        long id = server.getId();

        AgentAttache attache = createAttache(id, server, link);

        attache = notifyMonitorsOfConnection(attache, startup, false);

        return attache;
    }

    protected AgentAttache createAttache(long id, HostVO server, Link link) {
        s_logger.debug("create ConnectedAgentAttache for " + id);
        final AgentAttache attache = new ConnectedAgentAttache(this, id, link, server.getStatus() == Status.Maintenance || server.getStatus() == Status.ErrorInMaintenance
                || server.getStatus() == Status.PrepareForMaintenance);
        link.attach(attache);
        AgentAttache old = null;
        synchronized (_agents) {
            old = _agents.put(id, attache);
        }
        if (old != null) {
            old.disconnect(Status.Removed);
        }
        return attache;
    }

    protected AgentAttache createAttache(long id, HostVO server, ServerResource resource) {
        if (resource instanceof DummySecondaryStorageResource || resource instanceof KvmDummyResourceBase) {
            return new DummyAttache(this, id, false);
        }
        s_logger.debug("create DirectAgentAttache for " + id);
        final DirectAgentAttache attache = new DirectAgentAttache(this, id, resource, server.getStatus() == Status.Maintenance || server.getStatus() == Status.ErrorInMaintenance
                || server.getStatus() == Status.PrepareForMaintenance, this);
        AgentAttache old = null;
        synchronized (_agents) {
            old = _agents.put(id, attache);
        }
        if (old != null) {
            old.disconnect(Status.Removed);
        }
        return attache;
    }

    @Override
    public boolean maintenanceFailed(long hostId) {
        HostVO host = _hostDao.findById(hostId);
        if (host == null) {
            if (s_logger.isDebugEnabled()) {
                s_logger.debug("Cant not find host " + hostId);
            }
            return false;
        } else {
            return _hostDao.updateStatus(host, Event.UnableToMigrate, _nodeId);
        }
    }


    protected void updateHost(final HostVO host, final StartupCommand startup, final Host.Type type, final long msId) throws IllegalArgumentException {
        s_logger.debug("updateHost() called");

        String dataCenter = startup.getDataCenter();
        String pod = startup.getPod();
        String cluster = startup.getCluster();

        if (pod != null && dataCenter != null && pod.equalsIgnoreCase("default") && dataCenter.equalsIgnoreCase("default")) {
            List<HostPodVO> pods = _podDao.listAllIncludingRemoved();
            for (HostPodVO hpv : pods) {
                if (checkCIDR(type, hpv, startup.getPrivateIpAddress(), startup.getPrivateNetmask())) {
                    pod = hpv.getName();
                    dataCenter = _dcDao.findById(hpv.getDataCenterId()).getName();
                    break;
                }
            }
        }
        long dcId = -1;
        DataCenterVO dc = _dcDao.findByName(dataCenter);
        if (dc == null) {
            try {
                dcId = Long.parseLong(dataCenter);
                dc = _dcDao.findById(dcId);
            } catch (final NumberFormatException e) {
            }
        }
        if (dc == null) {
            throw new IllegalArgumentException("Host " + startup.getPrivateIpAddress() + " sent incorrect data center: " + dataCenter);
        }
        dcId = dc.getId();

        HostPodVO p = _podDao.findByName(pod, dcId);
        if (p == null) {
            try {
                final long podId = Long.parseLong(pod);
                p = _podDao.findById(podId);
            } catch (final NumberFormatException e) {
            }
        }
        Long podId = null;
        if (p == null) {
            if (type != Host.Type.SecondaryStorage && type != Host.Type.ExternalFirewall && type != Host.Type.ExternalLoadBalancer && type != Host.Type.TrafficMonitor) {

                /*
                 * s_logger.info("Unable to find the pod so we are creating one." ); p = createPod(pod, dcId,
                 * startup.getPrivateIpAddress(), NetUtils.getCidrSize(startup.getPrivateNetmask())); podId = p.getId();
                 */
                s_logger.error("Host " + startup.getPrivateIpAddress() + " sent incorrect pod: " + pod + " in " + dataCenter);
                throw new IllegalArgumentException("Host " + startup.getPrivateIpAddress() + " sent incorrect pod: " + pod + " in " + dataCenter);
            }
        } else {
            podId = p.getId();
        }

        Long clusterId = null;
        if (cluster != null) {
            try {
                clusterId = Long.valueOf(cluster);
            } catch (NumberFormatException e) {
                ClusterVO c = _clusterDao.findBy(cluster, podId);
                if (c == null) {
                    c = new ClusterVO(dcId, podId, cluster);
                    c = _clusterDao.persist(c);
                }
                clusterId = c.getId();
            }
        }

        if (type == Host.Type.Routing) {
            StartupRoutingCommand scc = (StartupRoutingCommand) startup;

            HypervisorType hypervisorType = scc.getHypervisorType();
            boolean doCidrCheck = true;

            ClusterVO clusterVO = _clusterDao.findById(clusterId);
            if(clusterVO == null){
                throw new IllegalArgumentException("Cluster with id " + clusterId + " does not exist, cannot add host with this clusterId");                
            }
            if (clusterVO.getHypervisorType() != scc.getHypervisorType()) {
                throw new IllegalArgumentException("Can't add host whose hypervisor type is: " + scc.getHypervisorType() + " into cluster: " + clusterId + " whose hypervisor type is: "
                        + clusterVO.getHypervisorType());
            }

            /*
             * KVM:Enforcement that all the hosts in the cluster have the same os type, for migration
             */
            if (scc.getHypervisorType() == HypervisorType.KVM) {
                List<HostVO> hostsInCluster = _hostDao.listByCluster(clusterId);
                if (!hostsInCluster.isEmpty()) {
                    HostVO oneHost = hostsInCluster.get(0);
                    _hostDao.loadDetails(oneHost);
                    String hostOsInCluster = oneHost.getDetail("Host.OS");
                    String hostOs = scc.getHostDetails().get("Host.OS");
                    if (!hostOsInCluster.equalsIgnoreCase(hostOs)) {
                        throw new IllegalArgumentException("Can't add host: " + startup.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster," + "in which there are "
                                + hostOsInCluster + " hosts added");
                    }
                }
            }

            // If this command is from the agent simulator, don't do the CIDR
            // check
            if (scc.getAgentTag() != null && startup.getAgentTag().equalsIgnoreCase("vmops-simulator")) {
                doCidrCheck = false;
            }

            // If this command is from a KVM agent, or from an agent that has a
            // null hypervisor type, don't do the CIDR check
            if (hypervisorType == null || hypervisorType == HypervisorType.KVM || hypervisorType == HypervisorType.VMware || hypervisorType == HypervisorType.BareMetal
                    || hypervisorType == HypervisorType.Simulator || hypervisorType == HypervisorType.Ovm) {
                doCidrCheck = false;
            }

            if (doCidrCheck) {
                s_logger.info("Host: " + host.getName() + " connected with hypervisor type: " + hypervisorType + ". Checking CIDR...");
            } else {
                s_logger.info("Host: " + host.getName() + " connected with hypervisor type: " + hypervisorType + ". Skipping CIDR check...");
            }

            if (doCidrCheck) {
                checkCIDR(type, p, dc, scc.getPrivateIpAddress(), scc.getPrivateNetmask());
            }

            // Check if the private/public IPs of the server are already in the
            // private/public IP address tables
            checkIPConflicts(type, p, dc, scc.getPrivateIpAddress(), scc.getPublicIpAddress(), scc.getPublicIpAddress(), scc.getPublicNetmask());
        }

        host.setDataCenterId(dc.getId());
        host.setPodId(podId);
        host.setClusterId(clusterId);
        host.setPrivateIpAddress(startup.getPrivateIpAddress());
        host.setPrivateNetmask(startup.getPrivateNetmask());
        host.setPrivateMacAddress(startup.getPrivateMacAddress());
        host.setPublicIpAddress(startup.getPublicIpAddress());
        host.setPublicMacAddress(startup.getPublicMacAddress());
        host.setPublicNetmask(startup.getPublicNetmask());
        host.setStorageIpAddress(startup.getStorageIpAddress());
        host.setStorageMacAddress(startup.getStorageMacAddress());
        host.setStorageNetmask(startup.getStorageNetmask());
        host.setVersion(startup.getVersion());
        host.setName(startup.getName());
        host.setType(type);
        host.setManagementServerId(msId);
        host.setStorageUrl(startup.getIqn());
        host.setLastPinged(System.currentTimeMillis() >> 10);
        if (startup instanceof StartupRoutingCommand) {
            final StartupRoutingCommand scc = (StartupRoutingCommand) startup;
            host.setCaps(scc.getCapabilities());
            host.setCpus(scc.getCpus());
            host.setTotalMemory(scc.getMemory());
            host.setSpeed(scc.getSpeed());
            HypervisorType hyType = scc.getHypervisorType();
            host.setHypervisorType(hyType);

        } else if (startup instanceof StartupStorageCommand) {
            final StartupStorageCommand ssc = (StartupStorageCommand) startup;
            host.setParent(ssc.getParent());
            host.setTotalSize(ssc.getTotalSize());
            host.setHypervisorType(HypervisorType.None);
            if (ssc.getNfsShare() != null) {
                host.setStorageUrl(ssc.getNfsShare());
            }
        }
        if (startup.getStorageIpAddressDeux() != null) {
            host.setStorageIpAddressDeux(startup.getStorageIpAddressDeux());
            host.setStorageMacAddressDeux(startup.getStorageMacAddressDeux());
            host.setStorageNetmaskDeux(startup.getStorageNetmaskDeux());
        }

    }

    // protected void upgradeAgent(final Link link, final byte[] request, final
    // String reason) {
    //
    // if (reason == UnsupportedVersionException.IncompatibleVersion) {
    // final UpgradeResponse response = new UpgradeResponse(request,
    // _upgradeMgr.getAgentUrl());
    // try {
    // s_logger.info("Asking for the agent to update due to incompatible version: "
    // + response.toString());
    // link.send(response.toBytes());
    // } catch (final ClosedChannelException e) {
    // s_logger.warn("Unable to send response due to connection closed: " +
    // response.toString());
    // }
    // return;
    // }
    //
    // assert (reason == UnsupportedVersionException.UnknownVersion) :
    // "Unknown reason: " + reason;
    // final UpgradeResponse response = new UpgradeResponse(request,
    // _upgradeMgr.getAgentUrl());
    // try {
    // s_logger.info("Asking for the agent to update due to unknown version: " +
    // response.toString());
    // link.send(response.toBytes());
    // } catch (final ClosedChannelException e) {
    // s_logger.warn("Unable to send response due to connection closed: " +
    // response.toString());
    // }
    // }

    protected class SimulateStartTask implements Runnable {
        ServerResource resource;
        Map<String, String> details;
        long id;
        ActionDelegate<Long> actionDelegate;

        public SimulateStartTask(long id, ServerResource resource, Map<String, String> details, ActionDelegate<Long> actionDelegate) {
            this.id = id;
            this.resource = resource;
            this.details = details;
            this.actionDelegate = actionDelegate;
        }

        @Override
        public void run() {
            try {
                if (s_logger.isDebugEnabled()) {
                    s_logger.debug("Simulating start for resource " + resource.getName() + " id " + id);
                }
                simulateStart(id, resource, details, false, null, null, false);
            } catch (Exception e) {
                s_logger.warn("Unable to simulate start on resource " + id + " name " + resource.getName(), e);
            } finally {
                if (actionDelegate != null) {
                    actionDelegate.action(new Long(id));
                }
                StackMaid.current().exitCleanup();
            }
        }
    }

    public class AgentHandler extends Task {
        public AgentHandler(Task.Type type, Link link, byte[] data) {
            super(type, link, data);
        }

        protected void processRequest(final Link link, final Request request) {
            AgentAttache attache = (AgentAttache) link.attachment();
            final Command[] cmds = request.getCommands();
            Command cmd = cmds[0];
            boolean logD = true;

            Response response = null;
            if (attache == null) {
                request.logD("Processing the first command ");
                if (!(cmd instanceof StartupCommand)) {
                    s_logger.warn("Throwing away a request because it came through as the first command on a connect: " + request);
                    return;
                }
                StartupCommand startup = (StartupCommand) cmd;
                // if ((_upgradeMgr.registerForUpgrade(-1, startup.getVersion())
                // == UpgradeManager.State.RequiresUpdate) &&
                // (_upgradeMgr.getAgentUrl() != null)) {
                // final UpgradeCommand upgrade = new
                // UpgradeCommand(_upgradeMgr.getAgentUrl());
                // final Request req = new Request(1, -1, -1, new Command[] {
                // upgrade }, true, true);
                // s_logger.info("Agent requires upgrade: " + req.toString());
                // try {
                // link.send(req.toBytes());
                // } catch (ClosedChannelException e) {
                // s_logger.warn("Unable to tell agent it should update.");
                // }
                // return;
                // }
                try {
                    StartupCommand[] startups = new StartupCommand[cmds.length];
                    for (int i = 0; i < cmds.length; i++) {
                        startups[i] = (StartupCommand) cmds[i];
                    }
                    attache = handleConnect(link, startups);
                } catch (final IllegalArgumentException e) {
                    _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, 0, new Long(0), "Agent from " + startup.getPrivateIpAddress() + " is unable to connect due to " + e.getMessage(), "Agent from "
                            + startup.getPrivateIpAddress() + " is unable to connect with " + request + " because of " + e.getMessage());
                    s_logger.warn("Unable to create attache for agent: " + request, e);
                    response = new Response(request, new StartupAnswer((StartupCommand) cmd, e.getMessage()), _nodeId, -1);
                } catch (ConnectionException e) {
                    _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, 0, new Long(0), "Agent from " + startup.getPrivateIpAddress() + " is unable to connect due to " + e.getMessage(), "Agent from "
                            + startup.getPrivateIpAddress() + " is unable to connect with " + request + " because of " + e.getMessage());
                    s_logger.warn("Unable to create attache for agent: " + request, e);
                    response = new Response(request, new StartupAnswer((StartupCommand) cmd, e.getMessage()), _nodeId, -1);
                } catch (final CloudRuntimeException e) {
                    _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, 0, new Long(0), "Agent from " + startup.getPrivateIpAddress() + " is unable to connect due to " + e.getMessage(), "Agent from "
                            + startup.getPrivateIpAddress() + " is unable to connect with " + request + " because of " + e.getMessage());
                    s_logger.warn("Unable to create attache for agent: " + request, e);
                }
                if (attache == null) {
                    if (response == null) {
                        s_logger.warn("Unable to create attache for agent: " + request);
                        response = new Response(request, new StartupAnswer((StartupCommand) request.getCommand(), "Unable to register this agent"), _nodeId, -1);
                    }
                    try {
                        link.send(response.toBytes(), true);
                    } catch (final ClosedChannelException e) {
                        s_logger.warn("Response was not sent: " + response);
                    }
                    return;
                }
            }

            final long hostId = attache.getId();

            if (s_logger.isDebugEnabled()) {
                if (cmd instanceof PingRoutingCommand) {
                    final PingRoutingCommand ping = (PingRoutingCommand) cmd;
                    if (ping.getNewStates().size() > 0) {
                        s_logger.debug("SeqA " + hostId + "-" + request.getSequence() + ": Processing " + request);
                    } else {
                        logD = false;
                        s_logger.debug("Ping from " + hostId);
                        s_logger.trace("SeqA " + hostId + "-" + request.getSequence() + ": Processing " + request);
                    }
                } else if (cmd instanceof PingCommand) {
                    logD = false;
                    s_logger.debug("Ping from " + hostId);
                    s_logger.trace("SeqA " + attache.getId() + "-" + request.getSequence() + ": Processing " + request);
                } else {
                    s_logger.debug("SeqA " + attache.getId() + "-" + request.getSequence() + ": Processing " + request);
                }
            }

            final Answer[] answers = new Answer[cmds.length];
            for (int i = 0; i < cmds.length; i++) {
                cmd = cmds[i];
                Answer answer = null;
                try {
                    if (cmd instanceof StartupRoutingCommand) {
                        final StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
                        answer = new StartupAnswer(startup, attache.getId(), getPingInterval());
                    } else if (cmd instanceof StartupProxyCommand) {
                        final StartupProxyCommand startup = (StartupProxyCommand) cmd;
                        answer = new StartupAnswer(startup, attache.getId(), getPingInterval());
                    } else if (cmd instanceof StartupSecondaryStorageCommand) {
                        final StartupSecondaryStorageCommand startup = (StartupSecondaryStorageCommand) cmd;
                        answer = new StartupAnswer(startup, attache.getId(), getPingInterval());
                    } else if (cmd instanceof StartupStorageCommand) {
                        final StartupStorageCommand startup = (StartupStorageCommand) cmd;
                        answer = new StartupAnswer(startup, attache.getId(), getPingInterval());
                    } else if (cmd instanceof ShutdownCommand) {
                        final ShutdownCommand shutdown = (ShutdownCommand) cmd;
                        final String reason = shutdown.getReason();
                        s_logger.info("Host " + attache.getId() + " has informed us that it is shutting down with reason " + reason + " and detail " + shutdown.getDetail());
                        if (reason.equals(ShutdownCommand.Update)) {
                            disconnect(attache, Event.UpdateNeeded, false);
                        } else if (reason.equals(ShutdownCommand.Requested)) {
                            disconnect(attache, Event.ShutdownRequested, false);
                        }
                        return;
                    } else if (cmd instanceof AgentControlCommand) {
                        answer = handleControlCommand(attache, (AgentControlCommand) cmd);
                    } else {
                        handleCommands(attache, request.getSequence(), new Command[] { cmd });
                        if (cmd instanceof PingCommand) {
                            long cmdHostId = ((PingCommand) cmd).getHostId();

                            // if the router is sending a ping, verify the
                            // gateway was pingable
                            if (cmd instanceof PingRoutingCommand) {
                                boolean gatewayAccessible = ((PingRoutingCommand) cmd).isGatewayAccessible();
                                HostVO host = _hostDao.findById(Long.valueOf(cmdHostId));
                                if (!gatewayAccessible) {
                                    // alert that host lost connection to
                                    // gateway (cannot ping the default route)
                                    DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId());
                                    HostPodVO podVO = _podDao.findById(host.getPodId());
                                    String hostDesc = "name: " + host.getName() + " (id:" + host.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName();

                                    _alertMgr.sendAlert(AlertManager.ALERT_TYPE_ROUTING, host.getDataCenterId(), host.getPodId(), "Host lost connection to gateway, " + hostDesc, "Host [" + hostDesc
                                            + "] lost connection to gateway (default route) and is possibly having network connection issues.");
                                } else {
                                    _alertMgr.clearAlert(AlertManager.ALERT_TYPE_ROUTING, host.getDataCenterId(), host.getPodId());
                                }
                            }
                            answer = new PingAnswer((PingCommand) cmd);
                        } else if (cmd instanceof ReadyAnswer) {
                            HostVO host = _hostDao.findById(attache.getId());
                            if (host == null) {
                                if (s_logger.isDebugEnabled()) {
                                    s_logger.debug("Cant not find host " + attache.getId());
                                }
                            }
                            answer = new Answer(cmd);
                        } else {
                            answer = new Answer(cmd);
                        }
                    }
                } catch (final Throwable th) {
                    s_logger.warn("Caught: ", th);
                    answer = new Answer(cmd, false, th.getMessage());
                }
                answers[i] = answer;
            }

            response = new Response(request, answers, _nodeId, attache.getId());
            if (s_logger.isDebugEnabled()) {
                if (logD) {
                    s_logger.debug("SeqA " + attache.getId() + "-" + response.getSequence() + ": Sending " + response);
                } else {
                    s_logger.trace("SeqA " + attache.getId() + "-" + response.getSequence() + ": Sending " + response);
                }
            }
            try {
                link.send(response.toBytes());
            } catch (final ClosedChannelException e) {
                s_logger.warn("Unable to send response because connection is closed: " + response);
            }
        }

        protected void processResponse(final Link link, final Response response) {
            final AgentAttache attache = (AgentAttache) link.attachment();
            if (attache == null) {
                s_logger.warn("Unable to process: " + response);
            }

            if (!attache.processAnswers(response.getSequence(), response)) {
                s_logger.info("Host " + attache.getId() + " - Seq " + response.getSequence() + ": Response is not processed: " + response);
            }
        }

        @Override
        protected void doTask(final Task task) throws Exception {
            Transaction txn = Transaction.open(Transaction.CLOUD_DB);
            try {
                final Type type = task.getType();
                if (type == Task.Type.DATA) {
                    final byte[] data = task.getData();
                    try {
                        final Request event = Request.parse(data);
                        if (event instanceof Response) {
                            processResponse(task.getLink(), (Response) event);
                        } else {
                            processRequest(task.getLink(), event);
                        }
                    } catch (final UnsupportedVersionException e) {
                        s_logger.warn(e.getMessage());
                        // upgradeAgent(task.getLink(), data, e.getReason());
                    }
                } else if (type == Task.Type.CONNECT) {
                } else if (type == Task.Type.DISCONNECT) {
                    final Link link = task.getLink();
                    final AgentAttache attache = (AgentAttache) link.attachment();
                    if (attache != null) {
                        disconnect(attache, Event.AgentDisconnected, true);
                    } else {
                        s_logger.info("Connection from " + link.getIpAddress() + " closed but no cleanup was done.");
                        link.close();
                        link.terminated();
                    }
                }
            } finally {
                StackMaid.current().exitCleanup();
                txn.close();
            }
        }
    }

    protected AgentManagerImpl() {
    }

}
