You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by al...@apache.org on 2012/07/31 22:40:02 UTC

[24/50] [abbrv] Move KVM related code into plugins/hypervisor/kvm, a new jar file is created: cloud-kvm.jar

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/FakeComputingResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/FakeComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/FakeComputingResource.java
new file mode 100644
index 0000000..83f6976
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/FakeComputingResource.java
@@ -0,0 +1,641 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.kvm.resource;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.AttachIsoCommand;
+import com.cloud.agent.api.AttachVolumeCommand;
+import com.cloud.agent.api.CheckHealthAnswer;
+import com.cloud.agent.api.CheckHealthCommand;
+import com.cloud.agent.api.CheckStateAnswer;
+import com.cloud.agent.api.CheckStateCommand;
+import com.cloud.agent.api.CheckVirtualMachineAnswer;
+import com.cloud.agent.api.CheckVirtualMachineCommand;
+import com.cloud.agent.api.CleanupNetworkRulesCmd;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.GetHostStatsAnswer;
+import com.cloud.agent.api.GetHostStatsCommand;
+import com.cloud.agent.api.GetStorageStatsAnswer;
+import com.cloud.agent.api.GetStorageStatsCommand;
+import com.cloud.agent.api.GetVmStatsAnswer;
+import com.cloud.agent.api.GetVmStatsCommand;
+import com.cloud.agent.api.ModifySshKeysCommand;
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
+import com.cloud.agent.api.ModifyStoragePoolCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.PingRoutingCommand;
+import com.cloud.agent.api.PingTestCommand;
+import com.cloud.agent.api.ReadyAnswer;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.RebootAnswer;
+import com.cloud.agent.api.RebootCommand;
+import com.cloud.agent.api.SecurityGroupRuleAnswer;
+import com.cloud.agent.api.SecurityGroupRulesCmd;
+import com.cloud.agent.api.StartAnswer;
+import com.cloud.agent.api.StartCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.agent.api.StartupRoutingCommand.VmState;
+import com.cloud.agent.api.StartupStorageCommand;
+import com.cloud.agent.api.StopAnswer;
+import com.cloud.agent.api.StopCommand;
+import com.cloud.agent.api.StoragePoolInfo;
+import com.cloud.agent.api.routing.SavePasswordCommand;
+import com.cloud.agent.api.routing.VmDataCommand;
+import com.cloud.agent.api.storage.CreateAnswer;
+import com.cloud.agent.api.storage.CreateCommand;
+import com.cloud.agent.api.storage.DestroyCommand;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
+import com.cloud.agent.api.to.NicTO;
+import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.agent.api.to.VolumeTO;
+import com.cloud.agent.dhcp.DhcpSnooper;
+import com.cloud.agent.dhcp.FakeDhcpSnooper;
+import com.cloud.agent.mockvm.MockVm;
+import com.cloud.agent.mockvm.MockVmMgr;
+import com.cloud.agent.mockvm.VmMgr;
+import com.cloud.agent.vmdata.JettyVmDataServer;
+import com.cloud.agent.vmdata.VmDataServer;
+import com.cloud.host.Host.Type;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.network.Networks.RouterPrivateIpStrategy;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.ServerResourceBase;
+import com.cloud.storage.Storage;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.Volume;
+import com.cloud.storage.template.TemplateInfo;
+import com.cloud.utils.PropertiesUtil;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.script.Script;
+import com.cloud.vm.VirtualMachine.State;
+
+/**
+ * Pretends to be a computing resource
+ * 
+ */
+@Local(value = { ServerResource.class })
+public class FakeComputingResource extends ServerResourceBase implements
+        ServerResource {
+    private static final Logger s_logger = Logger
+            .getLogger(FakeComputingResource.class);
+    private Map<String, Object> _params;
+    private VmMgr _vmManager = new MockVmMgr();
+    protected HashMap<String, State> _vms = new HashMap<String, State>(20);
+    protected DhcpSnooper _dhcpSnooper = new FakeDhcpSnooper();
+    protected VmDataServer _vmDataServer = new JettyVmDataServer();
+
+    @Override
+    public Type getType() {
+        return Type.Routing;
+    }
+
+    @Override
+    public StartupCommand[] initialize() {
+        Map<String, VmState> changes = null;
+
+        final List<Object> info = getHostInfo();
+
+        final StartupRoutingCommand cmd = new StartupRoutingCommand(
+                (Integer) info.get(0), (Long) info.get(1), (Long) info.get(2),
+                (Long) info.get(4), (String) info.get(3), HypervisorType.KVM,
+                RouterPrivateIpStrategy.HostLocal, changes);
+        fillNetworkInformation(cmd);
+        cmd.getHostDetails().putAll(getVersionStrings());
+        cmd.setCluster(getConfiguredProperty("cluster", "1"));
+        StoragePoolInfo pi = initializeLocalStorage();
+        StartupStorageCommand sscmd = new StartupStorageCommand();
+        sscmd.setPoolInfo(pi);
+        sscmd.setGuid(pi.getUuid());
+        sscmd.setDataCenter((String) _params.get("zone"));
+        sscmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL);
+
+        return new StartupCommand[] { cmd, sscmd };
+
+    }
+
+    private Map<String, String> getVersionStrings() {
+        Map<String, String> result = new HashMap<String, String>();
+        String hostOs = (String) _params.get("Host.OS");
+        String hostOsVer = (String) _params.get("Host.OS.Version");
+        String hostOsKernVer = (String) _params.get("Host.OS.Kernel.Version");
+        result.put("Host.OS", hostOs == null ? "Fedora" : hostOs);
+        result.put("Host.OS.Version", hostOsVer == null ? "14" : hostOsVer);
+        result.put("Host.OS.Kernel.Version",
+                hostOsKernVer == null ? "2.6.35.6-45.fc14.x86_64"
+                        : hostOsKernVer);
+        return result;
+    }
+
+    protected void fillNetworkInformation(final StartupCommand cmd) {
+
+        cmd.setPrivateIpAddress((String) _params.get("private.ip.address"));
+        cmd.setPrivateMacAddress((String) _params.get("private.mac.address"));
+        cmd.setPrivateNetmask((String) _params.get("private.ip.netmask"));
+
+        cmd.setStorageIpAddress((String) _params.get("private.ip.address"));
+        cmd.setStorageMacAddress((String) _params.get("private.mac.address"));
+        cmd.setStorageNetmask((String) _params.get("private.ip.netmask"));
+        cmd.setGatewayIpAddress((String) _params.get("gateway.ip.address"));
+
+    }
+
+    protected StoragePoolInfo initializeLocalStorage() {
+        String hostIp = (String) _params.get("private.ip.address");
+        String localStoragePath = (String) _params.get("local.storage.path");
+        String lh = hostIp + localStoragePath;
+        String uuid = UUID.nameUUIDFromBytes(lh.getBytes()).toString();
+
+        String capacity = (String) _params.get("local.storage.capacity");
+        String available = (String) _params.get("local.storage.avail");
+
+        return new StoragePoolInfo(uuid, hostIp, localStoragePath,
+                localStoragePath, StoragePoolType.Filesystem,
+                Long.parseLong(capacity), Long.parseLong(available));
+
+    }
+
+    @Override
+    public PingCommand getCurrentStatus(long id) {
+        final HashMap<String, State> newStates = new HashMap<String, State>();
+        _dhcpSnooper.syncIpAddr();
+        return new PingRoutingCommand(com.cloud.host.Host.Type.Routing, id,
+                newStates);
+    }
+
+    @Override
+    public Answer executeRequest(Command cmd) {
+        try {
+            if (cmd instanceof ReadyCommand) {
+                return execute((ReadyCommand) cmd);
+            } else if (cmd instanceof ModifySshKeysCommand) {
+                return execute((ModifySshKeysCommand) cmd);// TODO: remove
+            } else if (cmd instanceof GetHostStatsCommand) {
+                return execute((GetHostStatsCommand) cmd);
+            } else if (cmd instanceof PrimaryStorageDownloadCommand) {
+                return execute((PrimaryStorageDownloadCommand) cmd);
+
+            } else if (cmd instanceof StopCommand) {
+                return execute((StopCommand) cmd);
+            } else if (cmd instanceof GetVmStatsCommand) {
+                return execute((GetVmStatsCommand) cmd);
+            } else if (cmd instanceof RebootCommand) {
+                return execute((RebootCommand) cmd);
+            } else if (cmd instanceof CheckStateCommand) {
+                return executeRequest(cmd);
+            } else if (cmd instanceof CheckHealthCommand) {
+                return execute((CheckHealthCommand) cmd);
+            } else if (cmd instanceof PingTestCommand) {
+                return execute((PingTestCommand) cmd);
+            } else if (cmd instanceof CheckVirtualMachineCommand) {
+                return execute((CheckVirtualMachineCommand) cmd);
+            } else if (cmd instanceof ReadyCommand) {
+                return execute((ReadyCommand) cmd);
+            } else if (cmd instanceof StopCommand) {
+                return execute((StopCommand) cmd);
+            } else if (cmd instanceof CreateCommand) {
+                return execute((CreateCommand) cmd);
+            } else if (cmd instanceof DestroyCommand) {
+                return execute((DestroyCommand) cmd);
+            } else if (cmd instanceof PrimaryStorageDownloadCommand) {
+                return execute((PrimaryStorageDownloadCommand) cmd);
+            } else if (cmd instanceof GetStorageStatsCommand) {
+                return execute((GetStorageStatsCommand) cmd);
+            } else if (cmd instanceof ModifyStoragePoolCommand) {
+                return execute((ModifyStoragePoolCommand) cmd);
+            } else if (cmd instanceof SecurityGroupRulesCmd) {
+                return execute((SecurityGroupRulesCmd) cmd);
+            } else if (cmd instanceof StartCommand) {
+                return execute((StartCommand) cmd);
+            } else if (cmd instanceof CleanupNetworkRulesCmd) {
+                return execute((CleanupNetworkRulesCmd) cmd);
+            } else if (cmd instanceof SavePasswordCommand) {
+                return execute((SavePasswordCommand) cmd);
+            } else if (cmd instanceof VmDataCommand) {
+                return execute((VmDataCommand) cmd);
+            } else {
+                s_logger.warn("Unsupported command ");
+                return Answer.createUnsupportedCommandAnswer(cmd);
+            }
+        } catch (final IllegalArgumentException e) {
+            return new Answer(cmd, false, e.getMessage());
+        }
+    }
+
+    private Answer execute(CleanupNetworkRulesCmd cmd) {
+        return new Answer(cmd);
+    }
+
+    private Answer execute(SecurityGroupRulesCmd cmd) {
+        s_logger.info("Programmed network rules for vm " + cmd.getVmName()
+                + " guestIp=" + cmd.getGuestIp() + ",ingress numrules="
+                + cmd.getIngressRuleSet().length + ",egress numrules="
+                + cmd.getEgressRuleSet().length);
+        return new SecurityGroupRuleAnswer(cmd);
+    }
+
+    private Answer execute(ModifyStoragePoolCommand cmd) {
+        long capacity = getConfiguredProperty("local.storage.capacity",
+                10000000000L);
+        long used = 10000000L;
+        long available = capacity - used;
+        if (cmd.getAdd()) {
+
+            ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd,
+                    capacity, used, new HashMap<String, TemplateInfo>());
+
+            if (s_logger.isInfoEnabled())
+                s_logger.info("Sending ModifyStoragePoolCommand answer with capacity: "
+                        + capacity
+                        + ", used: "
+                        + used
+                        + ", available: "
+                        + available);
+            return answer;
+        } else {
+            if (s_logger.isInfoEnabled())
+                s_logger.info("ModifyNetfsStoragePoolCmd is not add command, cmd: "
+                        + cmd.toString());
+            return new Answer(cmd);
+        }
+    }
+
+    private Answer execute(GetStorageStatsCommand cmd) {
+        return new GetStorageStatsAnswer(cmd, getConfiguredProperty(
+                "local.storage.capacity", 100000000000L), 0L);
+    }
+
+    protected synchronized ReadyAnswer execute(ReadyCommand cmd) {
+        return new ReadyAnswer(cmd);
+    }
+
+    private Answer execute(PrimaryStorageDownloadCommand cmd) {
+        return new PrimaryStorageDownloadAnswer(cmd.getLocalPath(), 16000000L);
+    }
+
+    private Answer execute(ModifySshKeysCommand cmd) {
+        return new Answer(cmd, true, null);
+    }
+
+    @Override
+    protected String getDefaultScriptsDir() {
+        return null;
+    }
+
+    protected String getConfiguredProperty(String key, String defaultValue) {
+        String val = (String) _params.get(key);
+        return val == null ? defaultValue : val;
+    }
+
+    protected Long getConfiguredProperty(String key, Long defaultValue) {
+        String val = (String) _params.get(key);
+
+        if (val != null) {
+            Long result = Long.parseLong(val);
+            return result;
+        }
+        return defaultValue;
+    }
+
+    protected List<Object> getHostInfo() {
+        final ArrayList<Object> info = new ArrayList<Object>();
+        long speed = getConfiguredProperty("cpuspeed", 4000L);
+        long cpus = getConfiguredProperty("cpus", 4L);
+        long ram = getConfiguredProperty("memory", 16000L * 1024L * 1024L);
+        long dom0ram = Math.min(ram / 10, 768 * 1024 * 1024L);
+
+        String cap = getConfiguredProperty("capabilities", "hvm");
+        info.add((int) cpus);
+        info.add(speed);
+        info.add(ram);
+        info.add(cap);
+        info.add(dom0ram);
+        return info;
+
+    }
+
+    private Map<String, Object> getSimulatorProperties()
+            throws ConfigurationException {
+        final File file = PropertiesUtil.findConfigFile("simulator.properties");
+        if (file == null) {
+            throw new ConfigurationException(
+                    "Unable to find simulator.properties.");
+        }
+
+        s_logger.info("simulator.properties found at " + file.getAbsolutePath());
+        Properties properties = new Properties();
+        try {
+            properties.load(new FileInputStream(file));
+
+            final Map<String, Object> params = PropertiesUtil.toMap(properties);
+
+            return params;
+        } catch (final FileNotFoundException ex) {
+            throw new CloudRuntimeException("Cannot find the file: "
+                    + file.getAbsolutePath(), ex);
+        } catch (final IOException ex) {
+            throw new CloudRuntimeException("IOException in reading "
+                    + file.getAbsolutePath(), ex);
+        }
+    }
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params)
+            throws ConfigurationException {
+        Map<String, Object> simProps = getSimulatorProperties();
+        params.putAll(simProps);
+        setParams(params);
+        _vmManager.configure(params);
+        _dhcpSnooper.configure(name, params);
+        _vmDataServer.configure(name, params);
+        return true;
+    }
+
+    public void setParams(Map<String, Object> _params) {
+        this._params = _params;
+    }
+
+    public Map<String, Object> getParams() {
+        return _params;
+    }
+
+    protected synchronized StartAnswer execute(StartCommand cmd) {
+        VmMgr vmMgr = getVmManager();
+
+        VirtualMachineTO vmSpec = cmd.getVirtualMachine();
+        String vmName = vmSpec.getName();
+        State state = State.Stopped;
+
+        try {
+            if (!_vms.containsKey(vmName)) {
+                synchronized (_vms) {
+                    _vms.put(vmName, State.Starting);
+                }
+
+                MockVm vm = vmMgr.createVmFromSpec(vmSpec);
+                vmMgr.createVbd(vmSpec, vmName, vm);
+                vmMgr.createVif(vmSpec, vmName, vm);
+
+                state = State.Running;
+                for (NicTO nic : cmd.getVirtualMachine().getNics()) {
+                    if (nic.getType() == TrafficType.Guest) {
+                        InetAddress addr = _dhcpSnooper.getIPAddr(nic.getMac(),
+                                vmName);
+                        nic.setIp(addr.getHostAddress());
+                    }
+                }
+                _vmDataServer.handleVmStarted(cmd.getVirtualMachine());
+                return new StartAnswer(cmd);
+            } else {
+                String msg = "There is already a VM having the same name "
+                        + vmName;
+                s_logger.warn(msg);
+                return new StartAnswer(cmd, msg);
+            }
+        } catch (Exception ex) {
+
+        } finally {
+            synchronized (_vms) {
+                _vms.put(vmName, state);
+            }
+        }
+        return new StartAnswer(cmd);
+    }
+
+    protected synchronized StopAnswer execute(StopCommand cmd) {
+        VmMgr vmMgr = getVmManager();
+
+        StopAnswer answer = null;
+        String vmName = cmd.getVmName();
+
+        Integer port = vmMgr.getVncPort(vmName);
+
+        State state = null;
+        synchronized (_vms) {
+            state = _vms.get(vmName);
+            _vms.put(vmName, State.Stopping);
+        }
+        try {
+            String result = vmMgr.stopVM(vmName, false);
+            if (result != null) {
+                s_logger.info("Trying destroy on " + vmName);
+                if (result == Script.ERR_TIMEOUT) {
+                    result = vmMgr.stopVM(vmName, true);
+                }
+
+                s_logger.warn("Couldn't stop " + vmName);
+
+                if (result != null) {
+                    return new StopAnswer(cmd, result, false);
+                }
+            }
+
+            answer = new StopAnswer(cmd, null, port, true);
+
+            String result2 = vmMgr.cleanupVnet(cmd.getVnet());
+            if (result2 != null) {
+                result = result2 + (result != null ? ("\n" + result) : "");
+                answer = new StopAnswer(cmd, result, port, true);
+            }
+
+            _dhcpSnooper.cleanup(vmName, null);
+
+            return answer;
+        } finally {
+            if (answer == null || !answer.getResult()) {
+                synchronized (_vms) {
+                    _vms.put(vmName, state);
+                }
+            }
+        }
+    }
+
+    protected Answer execute(final VmDataCommand cmd) {
+        return _vmDataServer.handleVmDataCommand(cmd);
+    }
+
+    protected Answer execute(final SavePasswordCommand cmd) {
+        return new Answer(cmd);
+    }
+
+    protected Answer execute(RebootCommand cmd) {
+        VmMgr vmMgr = getVmManager();
+        vmMgr.rebootVM(cmd.getVmName());
+        return new RebootAnswer(cmd, "success", true);
+    }
+
+    private Answer execute(PingTestCommand cmd) {
+        return new Answer(cmd);
+    }
+
+    protected GetVmStatsAnswer execute(GetVmStatsCommand cmd) {
+        return null;
+    }
+
+    private VmMgr getVmManager() {
+        return _vmManager;
+    }
+
+    protected Answer execute(GetHostStatsCommand cmd) {
+        VmMgr vmMgr = getVmManager();
+        return new GetHostStatsAnswer(cmd, vmMgr.getHostCpuUtilization(),
+                vmMgr.getHostFreeMemory(), vmMgr.getHostTotalMemory(), 0, 0,
+                "SimulatedHost");
+    }
+
+    protected CheckStateAnswer execute(CheckStateCommand cmd) {
+        State state = getVmManager().checkVmState(cmd.getVmName());
+        return new CheckStateAnswer(cmd, state);
+    }
+
+    protected CheckHealthAnswer execute(CheckHealthCommand cmd) {
+        return new CheckHealthAnswer(cmd, true);
+    }
+
+    protected CheckVirtualMachineAnswer execute(
+            final CheckVirtualMachineCommand cmd) {
+        VmMgr vmMgr = getVmManager();
+        final String vmName = cmd.getVmName();
+
+        final State state = vmMgr.checkVmState(vmName);
+        Integer vncPort = null;
+        if (state == State.Running) {
+            vncPort = vmMgr.getVncPort(vmName);
+            synchronized (_vms) {
+                _vms.put(vmName, State.Running);
+            }
+        }
+        return new CheckVirtualMachineAnswer(cmd, state, vncPort);
+    }
+
+    protected Answer execute(final AttachVolumeCommand cmd) {
+        return new Answer(cmd);
+    }
+
+    protected Answer execute(final AttachIsoCommand cmd) {
+        return new Answer(cmd);
+    }
+
+    protected CreateAnswer execute(final CreateCommand cmd) {
+        try {
+
+            VolumeTO vol = new VolumeTO(cmd.getVolumeId(), Volume.Type.ROOT,
+                    com.cloud.storage.Storage.StoragePoolType.LVM, cmd
+                            .getPool().getUuid(), "dummy", "/mountpoint",
+                    "dummyPath", 1000L, null);
+            return new CreateAnswer(cmd, vol);
+        } catch (Throwable th) {
+            return new CreateAnswer(cmd, new Exception("Unexpected exception"));
+        }
+    }
+
+    protected HashMap<String, State> sync() {
+        Map<String, State> newStates;
+        Map<String, State> oldStates = null;
+
+        HashMap<String, State> changes = new HashMap<String, State>();
+
+        synchronized (_vms) {
+            newStates = getVmManager().getVmStates();
+            oldStates = new HashMap<String, State>(_vms.size());
+            oldStates.putAll(_vms);
+
+            for (Map.Entry<String, State> entry : newStates.entrySet()) {
+                String vm = entry.getKey();
+
+                State newState = entry.getValue();
+                State oldState = oldStates.remove(vm);
+
+                if (s_logger.isTraceEnabled()) {
+                    s_logger.trace("VM " + vm + ": xen has state " + newState
+                            + " and we have state "
+                            + (oldState != null ? oldState.toString() : "null"));
+                }
+
+                if (oldState == null) {
+                    _vms.put(vm, newState);
+                    changes.put(vm, newState);
+                } else if (oldState == State.Starting) {
+                    if (newState == State.Running) {
+                        _vms.put(vm, newState);
+                    } else if (newState == State.Stopped) {
+                        s_logger.debug("Ignoring vm " + vm
+                                + " because of a lag in starting the vm.");
+                    }
+                } else if (oldState == State.Stopping) {
+                    if (newState == State.Stopped) {
+                        _vms.put(vm, newState);
+                    } else if (newState == State.Running) {
+                        s_logger.debug("Ignoring vm " + vm
+                                + " because of a lag in stopping the vm. ");
+                    }
+                } else if (oldState != newState) {
+                    _vms.put(vm, newState);
+                    changes.put(vm, newState);
+                }
+            }
+
+            for (Map.Entry<String, State> entry : oldStates.entrySet()) {
+                String vm = entry.getKey();
+                State oldState = entry.getValue();
+
+                if (s_logger.isTraceEnabled()) {
+                    s_logger.trace("VM " + vm
+                            + " is now missing from xen so reporting stopped");
+                }
+
+                if (oldState == State.Stopping) {
+                    s_logger.debug("Ignoring VM " + vm
+                            + " in transition state stopping.");
+                    _vms.remove(vm);
+                } else if (oldState == State.Starting) {
+                    s_logger.debug("Ignoring VM " + vm
+                            + " in transition state starting.");
+                } else if (oldState == State.Stopped) {
+                    _vms.remove(vm);
+                } else {
+                    changes.put(entry.getKey(), State.Stopped);
+                }
+            }
+        }
+
+        return changes;
+    }
+
+    protected Answer execute(DestroyCommand cmd) {
+        return new Answer(cmd, true, null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java
new file mode 100644
index 0000000..e3615ad
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMGuestOsMapper.java
@@ -0,0 +1,169 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.kvm.resource;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+public class KVMGuestOsMapper {
+    private static final Logger s_logger = Logger
+            .getLogger(KVMGuestOsMapper.class);
+    private static Map<String, String> s_mapper = new HashMap<String, String>();
+    static {
+        s_mapper.put("CentOS 4.5 (32-bit)", "CentOS 4.5");
+        s_mapper.put("CentOS 4.6 (32-bit)", "CentOS 4.6");
+        s_mapper.put("CentOS 4.7 (32-bit)", "CentOS 4.7");
+        s_mapper.put("CentOS 4.8 (32-bit)", "CentOS 4.8");
+        s_mapper.put("CentOS 5.0 (32-bit)", "CentOS 5.0");
+        s_mapper.put("CentOS 5.0 (64-bit)", "CentOS 5.0");
+        s_mapper.put("CentOS 5.1 (32-bit)", "CentOS 5.1");
+        s_mapper.put("CentOS 5.1 (64-bit)", "CentOS 5.1");
+        s_mapper.put("CentOS 5.2 (32-bit)", "CentOS 5.2");
+        s_mapper.put("CentOS 5.2 (64-bit)", "CentOS 5.2");
+        s_mapper.put("CentOS 5.3 (32-bit)", "CentOS 5.3");
+        s_mapper.put("CentOS 5.3 (64-bit)", "CentOS 5.3");
+        s_mapper.put("CentOS 5.4 (32-bit)", "CentOS 5.4");
+        s_mapper.put("CentOS 5.4 (64-bit)", "CentOS 5.4");
+        s_mapper.put("CentOS 5.5 (32-bit)", "CentOS 5.5");
+        s_mapper.put("CentOS 5.5 (64-bit)", "CentOS 5.5");
+        s_mapper.put("Red Hat Enterprise Linux 2", "Red Hat Enterprise Linux 2");
+        s_mapper.put("Red Hat Enterprise Linux 3 (32-bit)",
+                "Red Hat Enterprise Linux 3");
+        s_mapper.put("Red Hat Enterprise Linux 3 (64-bit)",
+                "Red Hat Enterprise Linux 3");
+        s_mapper.put("Red Hat Enterprise Linux 4(64-bit)",
+                "Red Hat Enterprise Linux 4");
+        s_mapper.put("Red Hat Enterprise Linux 4.5 (32-bit)",
+                "Red Hat Enterprise Linux 4.5");
+        s_mapper.put("Red Hat Enterprise Linux 4.6 (32-bit)",
+                "Red Hat Enterprise Linux 4.6");
+        s_mapper.put("Red Hat Enterprise Linux 4.7 (32-bit)",
+                "Red Hat Enterprise Linux 4.7");
+        s_mapper.put("Red Hat Enterprise Linux 4.8 (32-bit)",
+                "Red Hat Enterprise Linux 4.8");
+        s_mapper.put("Red Hat Enterprise Linux 5.0 (32-bit)",
+                "Red Hat Enterprise Linux 5.0");
+        s_mapper.put("Red Hat Enterprise Linux 5.0 (64-bit)",
+                "Red Hat Enterprise Linux 5.0");
+        s_mapper.put("Red Hat Enterprise Linux 5.1 (32-bit)",
+                "Red Hat Enterprise Linux 5.1");
+        s_mapper.put("Red Hat Enterprise Linux 5.1 (32-bit)",
+                "Red Hat Enterprise Linux 5.1");
+        s_mapper.put("Red Hat Enterprise Linux 5.2 (32-bit)",
+                "Red Hat Enterprise Linux 5.2");
+        s_mapper.put("Red Hat Enterprise Linux 5.2 (64-bit)",
+                "Red Hat Enterprise Linux 5.2");
+        s_mapper.put("Red Hat Enterprise Linux 5.3 (32-bit)",
+                "Red Hat Enterprise Linux 5.3");
+        s_mapper.put("Red Hat Enterprise Linux 5.3 (64-bit)",
+                "Red Hat Enterprise Linux 5.3");
+        s_mapper.put("Red Hat Enterprise Linux 5.4 (32-bit)",
+                "Red Hat Enterprise Linux 5.4");
+        s_mapper.put("Red Hat Enterprise Linux 5.4 (64-bit)",
+                "Red Hat Enterprise Linux 5.4");
+        s_mapper.put("Red Hat Enterprise Linux 5.5 (32-bit)",
+                "Red Hat Enterprise Linux 5.5");
+        s_mapper.put("Red Hat Enterprise Linux 5.5 (64-bit)",
+                "Red Hat Enterprise Linux 5.5");
+        s_mapper.put("Red Hat Enterprise Linux 6.0 (32-bit)",
+                "Red Hat Enterprise Linux 6.0");
+        s_mapper.put("Red Hat Enterprise Linux 6.0 (64-bit)",
+                "Red Hat Enterprise Linux 6.0");
+        s_mapper.put("Fedora 13", "Fedora 13");
+        s_mapper.put("Fedora 12", "Fedora 12");
+        s_mapper.put("Fedora 11", "Fedora 11");
+        s_mapper.put("Fedora 10", "Fedora 10");
+        s_mapper.put("Fedora 9", "Fedora 9");
+        s_mapper.put("Fedora 8", "Fedora 8");
+        s_mapper.put("Ubuntu 10.04 (32-bit)", "Ubuntu 10.04");
+        s_mapper.put("Ubuntu 10.04 (64-bit)", "Ubuntu 10.04");
+        s_mapper.put("Ubuntu 10.10 (32-bit)", "Ubuntu 10.10");
+        s_mapper.put("Ubuntu 10.10 (64-bit)", "Ubuntu 10.10");
+        s_mapper.put("Ubuntu 9.10 (32-bit)", "Ubuntu 9.10");
+        s_mapper.put("Ubuntu 9.10 (64-bit)", "Ubuntu 9.10");
+        s_mapper.put("Ubuntu 9.04 (32-bit)", "Ubuntu 9.04");
+        s_mapper.put("Ubuntu 9.04 (64-bit)", "Ubuntu 9.04");
+        s_mapper.put("Ubuntu 8.10 (32-bit)", "Ubuntu 8.10");
+        s_mapper.put("Ubuntu 8.10 (64-bit)", "Ubuntu 8.10");
+        s_mapper.put("Ubuntu 8.04 (32-bit)", "Other Linux");
+        s_mapper.put("Ubuntu 8.04 (64-bit)", "Other Linux");
+        s_mapper.put("Debian GNU/Linux 5(32-bit)", "Debian GNU/Linux 5");
+        s_mapper.put("Debian GNU/Linux 5(64-bit)", "Debian GNU/Linux 5");
+        s_mapper.put("Debian GNU/Linux 4(32-bit)", "Debian GNU/Linux 4");
+        s_mapper.put("Debian GNU/Linux 4(64-bit)", "Debian GNU/Linux 4");
+        s_mapper.put("Debian GNU/Linux 6(64-bit)", "Debian GNU/Linux 6");
+        s_mapper.put("Debian GNU/Linux 6(32-bit)", "Debian GNU/Linux 6");
+        s_mapper.put("Other 2.6x Linux (32-bit)", "Other 2.6x Linux");
+        s_mapper.put("Other 2.6x Linux (64-bit)", "Other 2.6x Linux");
+        s_mapper.put("Other Linux (32-bit)", "Other Linux");
+        s_mapper.put("Other Linux (64-bit)", "Other Linux");
+        s_mapper.put("Other Ubuntu (32-bit)", "Other Linux");
+        s_mapper.put("Other Ubuntu (64-bit)", "Other Linux");
+        s_mapper.put("Asianux 3(32-bit)", "Other Linux");
+        s_mapper.put("Asianux 3(64-bit)", "Other Linux");
+        s_mapper.put("Windows 7 (32-bit)", "Windows 7");
+        s_mapper.put("Windows 7 (64-bit)", "Windows 7");
+        s_mapper.put("Windows Server 2003 Enterprise Edition(32-bit)",
+                "Windows Server 2003");
+        s_mapper.put("Windows Server 2003 Enterprise Edition(64-bit)",
+                "Windows Server 2003");
+        s_mapper.put("Windows Server 2003 DataCenter Edition(32-bit)",
+                "Windows Server 2003");
+        s_mapper.put("Windows Server 2003 DataCenter Edition(64-bit)",
+                "Windows Server 2003");
+        s_mapper.put("Windows Server 2003 Standard Edition(32-bit)",
+                "Windows Server 2003");
+        s_mapper.put("Windows Server 2003 Standard Edition(64-bit)",
+                "Windows Server 2003");
+        s_mapper.put("Windows Server 2003 Web Edition", "Windows Server 2003");
+        s_mapper.put("Microsoft Small Bussiness Server 2003",
+                "Windows Server 2003");
+        s_mapper.put("Windows Server 2008 (32-bit)", "Windows Server 2008");
+        s_mapper.put("Windows Server 2008 (64-bit)", "Windows Server 2008");
+        s_mapper.put("Windows Server 2008 R2 (64-bit)", "Windows Server 2008");
+        s_mapper.put("Windows 2000 Server SP4 (32-bit)", "Windows 2000");
+        s_mapper.put("Windows 2000 Server", "Windows 2000");
+        s_mapper.put("Windows 2000 Advanced Server", "Windows 2000");
+        s_mapper.put("Windows 2000 Professional", "Windows 2000");
+        s_mapper.put("Windows Vista (32-bit)", "Windows Vista");
+        s_mapper.put("Windows Vista (64-bit)", "Windows Vista");
+        s_mapper.put("Windows XP SP2 (32-bit)", "Windows XP");
+        s_mapper.put("Windows XP SP3 (32-bit)", "Windows XP");
+        s_mapper.put("Windows XP (32-bit)", "Windows XP");
+        s_mapper.put("Windows XP (64-bit)", "Windows XP");
+        s_mapper.put("Windows 98", "Windows 98");
+        s_mapper.put("Windows 95", "Windows 95");
+        s_mapper.put("Windows NT 4", "Windows NT");
+        s_mapper.put("Windows 3.1", "Windows 3.1");
+        s_mapper.put("Windows PV", "Other PV");
+        s_mapper.put("Other PV (32-bit)", "Other PV");
+        s_mapper.put("Other PV (64-bit)", "Other PV");
+
+    }
+
+    public static String getGuestOsName(String guestOsName) {
+        String guestOS = s_mapper.get(guestOsName);
+        if (guestOS == null) {
+            s_logger.debug("Can't find the mapping of guest os: " + guestOsName);
+            return "Other";
+        } else {
+            return guestOS;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHABase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHABase.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHABase.java
new file mode 100644
index 0000000..2cb60d7
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHABase.java
@@ -0,0 +1,219 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.kvm.resource;
+
+import java.io.File;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.libvirt.LibvirtException;
+import org.libvirt.StoragePool;
+import org.libvirt.StoragePoolInfo;
+import org.libvirt.StoragePoolInfo.StoragePoolState;
+
+import com.cloud.utils.script.OutputInterpreter;
+import com.cloud.utils.script.OutputInterpreter.AllLinesParser;
+import com.cloud.utils.script.Script;
+
+public class KVMHABase {
+    private long _timeout = 60000; /* 1 minutes */
+    protected static String _heartBeatPath;
+    protected long _heartBeatUpdateTimeout = 60000;
+    protected long _heartBeatUpdateFreq = 60000;
+    protected long _heartBeatUpdateMaxRetry = 3;
+
+    public static enum PoolType {
+        PrimaryStorage, SecondaryStorage
+    }
+
+    public static class NfsStoragePool {
+        String _poolUUID;
+        String _poolIp;
+        String _poolMountSourcePath;
+        String _mountDestPath;
+        PoolType _type;
+
+        public NfsStoragePool(String poolUUID, String poolIp,
+                String poolSourcePath, String mountDestPath, PoolType type) {
+            this._poolUUID = poolUUID;
+            this._poolIp = poolIp;
+            this._poolMountSourcePath = poolSourcePath;
+            this._mountDestPath = mountDestPath;
+            this._type = type;
+        }
+    }
+
+    protected String checkingMountPoint(NfsStoragePool pool, String poolName) {
+        String mountSource = pool._poolIp + ":" + pool._poolMountSourcePath;
+        String mountPaths = Script
+                .runSimpleBashScript("cat /proc/mounts | grep " + mountSource);
+        String destPath = pool._mountDestPath;
+
+        if (mountPaths != null) {
+            String token[] = mountPaths.split(" ");
+            String mountType = token[2];
+            String mountDestPath = token[1];
+            if (mountType.equalsIgnoreCase("nfs")) {
+                if (poolName != null && !mountDestPath.startsWith(destPath)) {
+                    /* we need to mount it under poolName */
+                    Script mount = new Script("/bin/bash", 60000);
+                    mount.add("-c");
+                    mount.add("mount " + mountSource + " " + destPath);
+                    String result = mount.execute();
+                    if (result != null) {
+                        destPath = null;
+                    }
+                    destroyVMs(destPath);
+                } else if (poolName == null) {
+                    destPath = mountDestPath;
+                }
+            }
+        } else {
+            /* Can't find the mount point? */
+            /* we need to mount it under poolName */
+            if (poolName != null) {
+                Script mount = new Script("/bin/bash", 60000);
+                mount.add("-c");
+                mount.add("mount " + mountSource + " " + destPath);
+                String result = mount.execute();
+                if (result != null) {
+                    destPath = null;
+                }
+
+                destroyVMs(destPath);
+            }
+        }
+
+        return destPath;
+    }
+
+    protected String getMountPoint(NfsStoragePool storagePool) {
+
+        StoragePool pool = null;
+        String poolName = null;
+        try {
+            pool = LibvirtConnection.getConnection()
+                    .storagePoolLookupByUUIDString(storagePool._poolUUID);
+            if (pool != null) {
+                StoragePoolInfo spi = pool.getInfo();
+                if (spi.state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) {
+                    pool.create(0);
+                } else {
+                    /*
+                     * Sometimes, the mount point is lost, even libvirt thinks
+                     * the storage pool still running
+                     */
+                }
+            }
+            poolName = pool.getName();
+        } catch (LibvirtException e) {
+
+        } finally {
+            try {
+                if (pool != null) {
+                    pool.free();
+                }
+            } catch (LibvirtException e) {
+
+            }
+        }
+
+        return checkingMountPoint(storagePool, poolName);
+    }
+
+    protected void destroyVMs(String mountPath) {
+        /* if there are VMs using disks under this mount path, destroy them */
+        Script cmd = new Script("/bin/bash", _timeout);
+        cmd.add("-c");
+        cmd.add("ps axu|grep qemu|grep " + mountPath + "* |awk '{print $2}'");
+        AllLinesParser parser = new OutputInterpreter.AllLinesParser();
+        String result = cmd.execute(parser);
+
+        if (result != null) {
+            return;
+        }
+
+        String pids[] = parser.getLines().split("\n");
+        for (String pid : pids) {
+            Script.runSimpleBashScript("kill -9 " + pid);
+        }
+    }
+
+    protected String getHBFile(String mountPoint, String hostIP) {
+        return mountPoint + File.separator + "KVMHA" + File.separator + "hb-"
+                + hostIP;
+    }
+
+    protected String getHBFolder(String mountPoint) {
+        return mountPoint + File.separator + "KVMHA" + File.separator;
+    }
+
+    protected String runScriptRetry(String cmdString,
+            OutputInterpreter interpreter) {
+        String result = null;
+        for (int i = 0; i < 3; i++) {
+            Script cmd = new Script("/bin/bash", _timeout);
+            cmd.add("-c");
+            cmd.add(cmdString);
+            if (interpreter != null)
+                result = cmd.execute(interpreter);
+            else {
+                result = cmd.execute();
+            }
+            if (result == Script.ERR_TIMEOUT) {
+                continue;
+            } else if (result == null) {
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    public static void main(String[] args) {
+
+        NfsStoragePool pool = new KVMHAMonitor.NfsStoragePool(null, null, null,
+                null, PoolType.PrimaryStorage);
+
+        KVMHAMonitor haWritter = new KVMHAMonitor(pool, "192.168.1.163", null);
+        Thread ha = new Thread(haWritter);
+        ha.start();
+
+        KVMHAChecker haChecker = new KVMHAChecker(haWritter.getStoragePools(),
+                "192.168.1.163");
+
+        ExecutorService exe = Executors.newFixedThreadPool(1);
+        Future<Boolean> future = exe.submit((Callable<Boolean>) haChecker);
+        try {
+            for (int i = 0; i < 10; i++) {
+                System.out.println(future.get());
+                future = exe.submit((Callable<Boolean>) haChecker);
+            }
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (ExecutionException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAChecker.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAChecker.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAChecker.java
new file mode 100644
index 0000000..68deca0
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAChecker.java
@@ -0,0 +1,84 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.kvm.resource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.utils.script.OutputInterpreter;
+import com.cloud.utils.script.Script;
+
+public class KVMHAChecker extends KVMHABase implements Callable<Boolean> {
+    private static final Logger s_logger = Logger.getLogger(KVMHAChecker.class);
+    private List<NfsStoragePool> _pools;
+    private String _hostIP;
+    private long _heartBeatCheckerTimeout = 360000; /* 6 minutes */
+
+    public KVMHAChecker(List<NfsStoragePool> pools, String host) {
+        this._pools = pools;
+        this._hostIP = host;
+    }
+
+    /*
+     * True means heartbeaing is on going, or we can't get it's status. False
+     * means heartbeating is stopped definitely
+     */
+    private Boolean checkingHB() {
+        List<Boolean> results = new ArrayList<Boolean>();
+        for (NfsStoragePool pool : _pools) {
+
+            Script cmd = new Script(_heartBeatPath, _heartBeatCheckerTimeout,
+                    s_logger);
+            cmd.add("-i", pool._poolIp);
+            cmd.add("-p", pool._poolMountSourcePath);
+            cmd.add("-m", pool._mountDestPath);
+            cmd.add("-h", _hostIP);
+            cmd.add("-r");
+            cmd.add("-t",
+                    String.valueOf(_heartBeatUpdateFreq/1000));
+            OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
+            String result = cmd.execute(parser);
+            s_logger.debug("pool: " + pool._poolIp);
+            s_logger.debug("reture: " + result);
+            s_logger.debug("parser: " + parser.getLine());
+            if (result == null && parser.getLine().contains("> DEAD <")) {
+                s_logger.debug("read heartbeat failed: " + result);
+                results.add(false);
+            } else {
+                results.add(true);
+            }
+        }
+
+        for (Boolean r : results) {
+            if (r) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public Boolean call() throws Exception {
+        // s_logger.addAppender(new org.apache.log4j.ConsoleAppender(new
+        // org.apache.log4j.PatternLayout(), "System.out"));
+        return checkingHB();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java
new file mode 100644
index 0000000..c4e121b
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java
@@ -0,0 +1,119 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.kvm.resource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.log4j.Logger;
+import com.cloud.utils.script.Script;
+
+public class KVMHAMonitor extends KVMHABase implements Runnable {
+    private static final Logger s_logger = Logger.getLogger(KVMHAMonitor.class);
+    private Map<String, NfsStoragePool> _storagePool = new ConcurrentHashMap<String, NfsStoragePool>();
+
+    private String _hostIP; /* private ip address */
+
+    public KVMHAMonitor(NfsStoragePool pool, String host, String scriptPath) {
+        if (pool != null) {
+            this._storagePool.put(pool._poolUUID, pool);
+        }
+        this._hostIP = host;
+        this._heartBeatPath = scriptPath;
+    }
+
+    public void addStoragePool(NfsStoragePool pool) {
+        synchronized (_storagePool) {
+            this._storagePool.put(pool._poolUUID, pool);
+        }
+    }
+
+    public void removeStoragePool(String uuid) {
+        synchronized (_storagePool) {
+            this._storagePool.remove(uuid);
+        }
+    }
+
+    public List<NfsStoragePool> getStoragePools() {
+        synchronized (_storagePool) {
+            return new ArrayList<NfsStoragePool>(_storagePool.values());
+        }
+    }
+
+    private class Monitor implements Runnable {
+
+        @Override
+        public void run() {
+            synchronized (_storagePool) {
+                for (NfsStoragePool primaryStoragePool : _storagePool.values()) {
+                    String result = null;
+                    for (int i = 0; i < 5; i++) {
+                        Script cmd = new Script(_heartBeatPath,
+                                _heartBeatUpdateTimeout, s_logger);
+                        cmd.add("-i", primaryStoragePool._poolIp);
+                        cmd.add("-p", primaryStoragePool._poolMountSourcePath);
+                        cmd.add("-m", primaryStoragePool._mountDestPath);
+                        cmd.add("-h", _hostIP);
+                        result = cmd.execute();
+                        if (result != null) {
+                            s_logger.warn("write heartbeat failed: " + result
+                                    + ", retry: " + i);
+                        } else {
+                            break;
+                        }
+                    }
+
+                    if (result != null) {
+                        s_logger.warn("write heartbeat failed: " + result
+                                + "; reboot the host");
+                        Script cmd = new Script(_heartBeatPath,
+                                _heartBeatUpdateTimeout, s_logger);
+                        cmd.add("-i", primaryStoragePool._poolIp);
+                        cmd.add("-p", primaryStoragePool._poolMountSourcePath);
+                        cmd.add("-m", primaryStoragePool._mountDestPath);
+                        cmd.add("-c");
+                        result = cmd.execute();
+                    }
+                }
+            }
+
+        }
+    }
+
+    @Override
+    public void run() {
+        // s_logger.addAppender(new org.apache.log4j.ConsoleAppender(new
+        // org.apache.log4j.PatternLayout(), "System.out"));
+        while (true) {
+            Thread monitorThread = new Thread(new Monitor());
+            monitorThread.start();
+            try {
+                monitorThread.join();
+            } catch (InterruptedException e) {
+
+            }
+
+            try {
+                Thread.sleep(_heartBeatUpdateFreq);
+            } catch (InterruptedException e) {
+
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/7a0a9231/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtCapXMLParser.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtCapXMLParser.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtCapXMLParser.java
new file mode 100644
index 0000000..704af23
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtCapXMLParser.java
@@ -0,0 +1,194 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.hypervisor.kvm.resource;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+
+import org.apache.log4j.Logger;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * @author chiradeep
+ * 
+ */
+public class LibvirtCapXMLParser extends LibvirtXMLParser {
+    private boolean _host = false;
+    private boolean _guest = false;
+    private boolean _osType = false;
+    private boolean _domainTypeKVM = false;
+    private boolean _emulatorFlag = false;
+    private final StringBuffer _emulator = new StringBuffer();
+    private final StringBuffer _capXML = new StringBuffer();
+    private static final Logger s_logger = Logger
+            .getLogger(LibvirtCapXMLParser.class);
+    private final ArrayList<String> guestOsTypes = new ArrayList<String>();
+
+    @Override
+    public void endElement(String uri, String localName, String qName)
+            throws SAXException {
+        if (qName.equalsIgnoreCase("host")) {
+            _host = false;
+        } else if (qName.equalsIgnoreCase("os_type")) {
+            _osType = false;
+        } else if (qName.equalsIgnoreCase("guest")) {
+            _guest = false;
+        } else if (qName.equalsIgnoreCase("domain")) {
+            _domainTypeKVM = false;
+        } else if (qName.equalsIgnoreCase("emulator")) {
+            _emulatorFlag = false;
+
+        } else if (_host) {
+            _capXML.append("<").append("/").append(qName).append(">");
+        }
+    }
+
+    @Override
+    public void characters(char[] ch, int start, int length)
+            throws SAXException {
+        if (_host) {
+            _capXML.append(ch, start, length);
+        } else if (_osType) {
+            guestOsTypes.add(new String(ch, start, length));
+        } else if (_emulatorFlag) {
+            _emulator.append(ch, start, length);
+        }
+    }
+
+    @Override
+    public void startElement(String uri, String localName, String qName,
+            Attributes attributes) throws SAXException {
+        if (qName.equalsIgnoreCase("host")) {
+            _host = true;
+        } else if (qName.equalsIgnoreCase("guest")) {
+            _guest = true;
+        } else if (qName.equalsIgnoreCase("os_type")) {
+            if (_guest) {
+                _osType = true;
+            }
+        } else if (qName.equalsIgnoreCase("domain")) {
+            for (int i = 0; i < attributes.getLength(); i++) {
+                if (attributes.getQName(i).equalsIgnoreCase("type")
+                        && attributes.getValue(i).equalsIgnoreCase("kvm")) {
+                    _domainTypeKVM = true;
+                }
+            }
+        } else if (qName.equalsIgnoreCase("emulator") && _domainTypeKVM) {
+            _emulatorFlag = true;
+            _emulator.delete(0, _emulator.length());
+        } else if (_host) {
+            _capXML.append("<").append(qName);
+            for (int i = 0; i < attributes.getLength(); i++) {
+                _capXML.append(" ").append(attributes.getQName(i)).append("=")
+                        .append(attributes.getValue(i));
+            }
+            _capXML.append(">");
+        }
+
+    }
+
+    public String parseCapabilitiesXML(String capXML) {
+        if (!_initialized) {
+            return null;
+        }
+        try {
+            _sp.parse(new InputSource(new StringReader(capXML)), this);
+            return _capXML.toString();
+        } catch (SAXException se) {
+            s_logger.warn(se.getMessage());
+        } catch (IOException ie) {
+            s_logger.error(ie.getMessage());
+        }
+        return null;
+    }
+
+    public ArrayList<String> getGuestOsType() {
+        return guestOsTypes;
+    }
+
+    public String getEmulator() {
+        return _emulator.toString();
+    }
+
+    public static void main(String[] args) {
+        String capXML = "<capabilities>" + "  <host>" + "    <cpu>"
+                + "      <arch>x86_64</arch>" + "      <model>core2duo</model>"
+                + "      <topology sockets='1' cores='2' threads='1'/>"
+                + "      <feature name='lahf_lm'/>"
+                + "      <feature name='xtpr'/>"
+                + "      <feature name='cx16'/>"
+                + "      <feature name='tm2'/>" + "      <feature name='est'/>"
+                + "      <feature name='vmx'/>"
+                + "      <feature name='ds_cpl'/>"
+                + "      <feature name='pbe'/>" + "      <feature name='tm'/>"
+                + "      <feature name='ht'/>" + "      <feature name='ss'/>"
+                + "      <feature name='acpi'/>" + "      <feature name='ds'/>"
+                + "    </cpu>" + "    <migration_features>" + "      <live/>"
+                + "      <uri_transports>"
+                + "        <uri_transport>tcp</uri_transport>"
+                + "      </uri_transports>" + "    </migration_features>"
+                + "    <topology>" + "      <cells num='1'>"
+                + "        <cell id='0'>" + "          <cpus num='2'>"
+                + "            <cpu id='0'/>" + "            <cpu id='1'/>"
+                + "          </cpus>" + "        </cell>" + "      </cells>"
+                + "    </topology>" + "  </host>" + "" + "  <guest>"
+                + "    <os_type>hvm</os_type>" + "    <arch name='i686'>"
+                + "      <wordsize>32</wordsize>"
+                + "      <emulator>/usr/bin/qemu</emulator>"
+                + "      <machine>pc-0.11</machine>"
+                + "      <machine canonical='pc-0.11'>pc</machine>"
+                + "      <machine>pc-0.10</machine>"
+                + "      <machine>isapc</machine>"
+                + "      <domain type='qemu'>" + "      </domain>"
+                + "      <domain type='kvm'>"
+                + "        <emulator>/usr/bin/qemu-kvm</emulator>"
+                + "        <machine>pc-0.11</machine>"
+                + "        <machine canonical='pc-0.11'>pc</machine>"
+                + "        <machine>pc-0.10</machine>"
+                + "        <machine>isapc</machine>" + "      </domain>"
+                + "    </arch>" + "    <features>" + "      <cpuselection/>"
+                + "      <pae/>" + "      <nonpae/>"
+                + "      <acpi default='on' toggle='yes'/>"
+                + "      <apic default='on' toggle='no'/>" + "    </features>"
+                + "  </guest>" + "  <guest>" + "    <os_type>hvm</os_type>"
+                + "    <arch name='x86_64'>" + "      <wordsize>64</wordsize>"
+                + "      <emulator>/usr/bin/qemu-system-x86_64</emulator>"
+                + "      <machine>pc-0.11</machine>"
+                + "      <machine canonical='pc-0.11'>pc</machine>"
+                + "      <machine>pc-0.10</machine>"
+                + "      <machine>isapc</machine>"
+                + "      <domain type='qemu'>" + "      </domain>"
+                + "      <domain type='kvm'>"
+                + "        <emulator>/usr/bin/qemu-kvm</emulator>"
+                + "        <machine>pc-0.11</machine>"
+                + "        <machine canonical='pc-0.11'>pc</machine>"
+                + "        <machine>pc-0.10</machine>"
+                + "        <machine>isapc</machine>" + "      </domain>"
+                + "    </arch>" + "    <features>" + "      <cpuselection/>"
+                + "      <acpi default='on' toggle='yes'/>"
+                + "      <apic default='on' toggle='no'/>" + "    </features>"
+                + "  </guest>" + "</capabilities>";
+
+        LibvirtCapXMLParser parser = new LibvirtCapXMLParser();
+        String cap = parser.parseCapabilitiesXML(capXML);
+        System.out.println(parser.getGuestOsType());
+        System.out.println(parser.getEmulator());
+    }
+}