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());
+ }
+}