diff --git a/agent/src/com/cloud/agent/resource/DummyResource.java b/agent/src/com/cloud/agent/resource/DummyResource.java index 37a8b3d67e7..4918207546c 100755 --- a/agent/src/com/cloud/agent/resource/DummyResource.java +++ b/agent/src/com/cloud/agent/resource/DummyResource.java @@ -169,7 +169,7 @@ public class DummyResource implements ServerResource { 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); + RouterPrivateIpStrategy.HostLocal, changes, null); fillNetworkInformation(cmd); cmd.getHostDetails().putAll(getVersionStrings()); cmd.setCluster(getConfiguredProperty("cluster", "1")); diff --git a/api/src/com/cloud/agent/api/HostVmStateReportEntry.java b/api/src/com/cloud/agent/api/HostVmStateReportEntry.java index 7bcb50f361a..0b1a01e97e7 100644 --- a/api/src/com/cloud/agent/api/HostVmStateReportEntry.java +++ b/api/src/com/cloud/agent/api/HostVmStateReportEntry.java @@ -19,16 +19,29 @@ package com.cloud.agent.api; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.PowerState; +// +// TODO vmsync +// We should also have a HostVmStateReport class instead of using raw Map<> data structure, +// for now, we store host-specific info at each VM entry and host fields are fixed +// +// This needs to be refactor-ed afterwards +// public class HostVmStateReportEntry { VirtualMachine.PowerState state; + + // host name or host uuid String host; + + // XS needs Xen Tools version info + String hostToolsVersion; public HostVmStateReportEntry() { } - public HostVmStateReportEntry(PowerState state, String host) { + public HostVmStateReportEntry(PowerState state, String host, String hostToolsVersion) { this.state = state; this.host = host; + this.hostToolsVersion = hostToolsVersion; } public PowerState getState() { @@ -38,4 +51,8 @@ public class HostVmStateReportEntry { public String getHost() { return host; } + + public String getHostToolsVersion() { + return hostToolsVersion; + } } diff --git a/core/src/com/cloud/agent/api/PingRoutingCommand.java b/core/src/com/cloud/agent/api/PingRoutingCommand.java index e25ac62786f..cffa7ecab21 100755 --- a/core/src/com/cloud/agent/api/PingRoutingCommand.java +++ b/core/src/com/cloud/agent/api/PingRoutingCommand.java @@ -22,21 +22,33 @@ import com.cloud.host.Host; import com.cloud.vm.VirtualMachine.State; public class PingRoutingCommand extends PingCommand { - Map newStates; + + // TODO vmsync { + Map newStates; + // TODO vmsync } + + Map _hostVmStateReport; + boolean _gatewayAccessible = true; boolean _vnetAccessible = true; protected PingRoutingCommand() { } - public PingRoutingCommand(Host.Type type, long id, Map states) { + public PingRoutingCommand(Host.Type type, long id, Map states, + Map hostVmStateReport) { super(type, id); this.newStates = states; + this._hostVmStateReport = hostVmStateReport; } public Map getNewStates() { return newStates; } + + public Map getHostVmStateReport() { + return this._hostVmStateReport; + } public boolean isGatewayAccessible() { return _gatewayAccessible; diff --git a/core/src/com/cloud/agent/api/PingRoutingWithNwGroupsCommand.java b/core/src/com/cloud/agent/api/PingRoutingWithNwGroupsCommand.java index 51226bc36c1..5a25a7583ce 100644 --- a/core/src/com/cloud/agent/api/PingRoutingWithNwGroupsCommand.java +++ b/core/src/com/cloud/agent/api/PingRoutingWithNwGroupsCommand.java @@ -31,8 +31,10 @@ public class PingRoutingWithNwGroupsCommand extends PingRoutingCommand { super(); } - public PingRoutingWithNwGroupsCommand(Host.Type type, long id, Map states, HashMap> nwGrpStates) { - super(type, id, states); + public PingRoutingWithNwGroupsCommand(Host.Type type, long id, + Map states, Map hostVmStateReport, + HashMap> nwGrpStates) { + super(type, id, states, hostVmStateReport); newGroupStates = nwGrpStates; } diff --git a/core/src/com/cloud/agent/api/PingRoutingWithOvsCommand.java b/core/src/com/cloud/agent/api/PingRoutingWithOvsCommand.java index d44987b20fd..b87dd0a7e96 100644 --- a/core/src/com/cloud/agent/api/PingRoutingWithOvsCommand.java +++ b/core/src/com/cloud/agent/api/PingRoutingWithOvsCommand.java @@ -31,8 +31,10 @@ public class PingRoutingWithOvsCommand extends PingRoutingCommand { } public PingRoutingWithOvsCommand(Host.Type type, long id, - Map states, List> ovsStates) { - super(type, id, states); + Map states, Map hostVmStateReport, + List> ovsStates) { + super(type, id, states, hostVmStateReport); + this.states = ovsStates; } diff --git a/core/src/com/cloud/agent/api/StartupRoutingCommand.java b/core/src/com/cloud/agent/api/StartupRoutingCommand.java index f312e0fc72d..c75b6d1e73f 100755 --- a/core/src/com/cloud/agent/api/StartupRoutingCommand.java +++ b/core/src/com/cloud/agent/api/StartupRoutingCommand.java @@ -48,8 +48,18 @@ public class StartupRoutingCommand extends StartupCommand { long memory; long dom0MinMemory; boolean poolSync; + + // VM power state report is added in a side-by-side way as old VM state report + // this is to allow a graceful migration from the old VM state sync model to the new model + // + // side-by-side addition of power state sync + Map _hostVmStateReport; + + // TODO vmsync + // deprecated, will delete after full replacement Map vms; HashMap> _clusterVMStates; + String caps; String pool; HypervisorType hypervisorType; @@ -70,8 +80,10 @@ public class StartupRoutingCommand extends StartupCommand { String caps, HypervisorType hypervisorType, RouterPrivateIpStrategy privIpStrategy, - Map vms) { - this(cpus, speed, memory, dom0MinMemory, caps, hypervisorType, vms); + Map vms, + Map hostVmStateReport + ) { + this(cpus, speed, memory, dom0MinMemory, caps, hypervisorType, vms, hostVmStateReport); getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStrategy.toString()); } @@ -82,9 +94,11 @@ public class StartupRoutingCommand extends StartupCommand { String caps, HypervisorType hypervisorType, RouterPrivateIpStrategy privIpStrategy) { -this(cpus, speed, memory, dom0MinMemory, caps, hypervisorType, new HashMap(), new HashMap()); -getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStrategy.toString()); -} + this(cpus, speed, memory, dom0MinMemory, caps, hypervisorType, new HashMap(), + new HashMap(), new HashMap()); + + getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStrategy.toString()); + } public StartupRoutingCommand(int cpus, long speed, @@ -93,13 +107,15 @@ getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStr final String caps, final HypervisorType hypervisorType, final Map hostDetails, - Map vms) { + Map vms, + Map hostVmStateReport) { super(Host.Type.Routing); this.cpus = cpus; this.speed = speed; this.memory = memory; this.dom0MinMemory = dom0MinMemory; this.vms = vms; + this._hostVmStateReport = hostVmStateReport; this.hypervisorType = hypervisorType; this.hostDetails = hostDetails; this.caps = caps; @@ -108,12 +124,14 @@ getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStr public StartupRoutingCommand(int cpus2, long speed2, long memory2, long dom0MinMemory2, String caps2, HypervisorType hypervisorType2, - Map vms2) { - this(cpus2, speed2, memory2, dom0MinMemory2, caps2, hypervisorType2, new HashMap(), vms2); + Map vms2, Map hostVmStateReport + ) { + this(cpus2, speed2, memory2, dom0MinMemory2, caps2, hypervisorType2, new HashMap(), vms2, hostVmStateReport); } - public StartupRoutingCommand(int cpus, long speed, long memory, long dom0MinMemory, final String caps, final HypervisorType hypervisorType, final Map hostDetails, Map vms, String hypervisorVersion) { - this(cpus, speed, memory, dom0MinMemory, caps, hypervisorType, hostDetails, vms); + public StartupRoutingCommand(int cpus, long speed, long memory, long dom0MinMemory, final String caps, final HypervisorType hypervisorType, final Map hostDetails, + Map vms, Map vmPowerStates, String hypervisorVersion) { + this(cpus, speed, memory, dom0MinMemory, caps, hypervisorType, hostDetails, vms, vmPowerStates); this.hypervisorVersion = hypervisorVersion; } @@ -229,5 +247,13 @@ getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStr public void setHypervisorVersion(String hypervisorVersion) { this.hypervisorVersion = hypervisorVersion; } + + public Map getHostVmStateReport() { + return this._hostVmStateReport; + } + + public void setHostVmStateReport(Map hostVmStateReport) { + this._hostVmStateReport = hostVmStateReport; + } } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java index fa7abd58331..2418a194685 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java @@ -31,7 +31,6 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; - import org.apache.cloudstack.api.ApiConstants; import com.cloud.agent.IAgentControl; @@ -41,6 +40,7 @@ import com.cloud.agent.api.CheckNetworkCommand; import com.cloud.agent.api.CheckVirtualMachineAnswer; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.MaintainAnswer; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateAnswer; @@ -77,6 +77,7 @@ import com.cloud.utils.script.Script2; import com.cloud.utils.script.Script2.ParamType; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.VMInstanceDao; @@ -332,10 +333,36 @@ public class BareMetalResourceBase extends ManagerBase implements ServerResource return states; } + + protected Map getHostVmStateReport() { + Map states = new HashMap(); + if (hostId != null) { + vmDao = ComponentContext.getComponent(VMInstanceDao.class); + final List vms = vmDao.listByHostId(hostId); + for (VMInstanceVO vm : vms) { + states.put( + vm.getInstanceName(), + new HostVmStateReportEntry( + vm.getState() == State.Running ? PowerState.PowerOn : PowerState.PowerOff, "host-" + hostId, null + ) + ); + } + } + /* + * Map changes = new HashMap(); + * + * if (_vmName != null) { State state = getVmState(); if (state != null) + * { changes.put(_vmName, state); } } + */ + + return states; + } @Override public StartupCommand[] initialize() { - StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, new HashMap(), null); + StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, + new HashMap(), null, null); + cmd.setDataCenter(_zone); cmd.setPod(_pod); cmd.setCluster(_cluster); @@ -372,7 +399,7 @@ public class BareMetalResourceBase extends ManagerBase implements ServerResource return null; } - return new PingRoutingCommand(getType(), id, deltaSync()); + return new PingRoutingCommand(getType(), id, deltaSync(), getHostVmStateReport()); } protected Answer execute(IpmISetBootDevCommand cmd) { diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResourceBase.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResourceBase.java index 2a17a436842..f992fe9af3b 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResourceBase.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResourceBase.java @@ -32,6 +32,7 @@ import org.apache.log4j.Logger; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.ReadyAnswer; @@ -129,7 +130,8 @@ public class BaremetalDhcpResourceBase extends ManagerBase implements ServerReso @Override public PingCommand getCurrentStatus(long id) { //TODO: check server - return new PingRoutingCommand(getType(), id, new HashMap()); + return new PingRoutingCommand(getType(), id, new HashMap(), + new HashMap()); } protected ReadyAnswer execute(ReadyCommand cmd) { diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpdResource.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpdResource.java index a27a6f26896..dc778125777 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpdResource.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpdResource.java @@ -31,6 +31,7 @@ import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.routing.DhcpEntryCommand; @@ -105,7 +106,8 @@ public class BaremetalDhcpdResource extends BaremetalDhcpResourceBase { return null; } else { SSHCmdHelper.releaseSshConnection(sshConnection); - return new PingRoutingCommand(getType(), id, new HashMap()); + return new PingRoutingCommand(getType(), id, new HashMap(), + new HashMap()); } } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDnsmasqResource.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDnsmasqResource.java index d0fb2b4c098..19a4d903609 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDnsmasqResource.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDnsmasqResource.java @@ -32,6 +32,7 @@ import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.routing.DhcpEntryCommand; @@ -98,7 +99,8 @@ public class BaremetalDnsmasqResource extends BaremetalDhcpResourceBase { return null; } else { SSHCmdHelper.releaseSshConnection(sshConnection); - return new PingRoutingCommand(getType(), id, new HashMap()); + return new PingRoutingCommand(getType(), id, new HashMap(), + new HashMap()); } } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java index 7a7a5153e5c..e4f0cee6fab 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java @@ -29,6 +29,7 @@ import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.routing.VmDataCommand; @@ -106,7 +107,8 @@ public class BaremetalKickStartPxeResource extends BaremetalPxeResourceBase { return null; } else { SSHCmdHelper.releaseSshConnection(sshConnection); - return new PingRoutingCommand(getType(), id, new HashMap()); + return new PingRoutingCommand(getType(), id, new HashMap(), + new HashMap()); } } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java index 2fb54154489..59efe245224 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java @@ -32,6 +32,7 @@ import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.baremetal.PreparePxeServerAnswer; @@ -142,7 +143,8 @@ public class BaremetalPingPxeResource extends BaremetalPxeResourceBase { return null; } else { SSHCmdHelper.releaseSshConnection(sshConnection); - return new PingRoutingCommand(getType(), id, new HashMap()); + return new PingRoutingCommand(getType(), id, new HashMap(), + new HashMap()); } } diff --git a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java index 194ad77b05d..165d706d006 100644 --- a/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java +++ b/plugins/hypervisors/hyperv/src/com/cloud/hypervisor/hyperv/resource/HypervDirectConnectResource.java @@ -42,7 +42,6 @@ import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; import com.google.gson.Gson; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckRouterAnswer; import com.cloud.agent.api.CheckRouterCommand; @@ -51,6 +50,7 @@ import com.cloud.agent.api.CheckS2SVpnConnectionsCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.GetDomRVersionAnswer; import com.cloud.agent.api.GetDomRVersionCmd; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.NetworkUsageAnswer; import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.PingCommand; @@ -158,7 +158,8 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.Hyperv, RouterPrivateIpStrategy.HostLocal, - new HashMap()); + new HashMap(), + new HashMap()); // Identity within the data centre is decided by CloudStack kernel, // and passed via ServerResource.configure() @@ -293,7 +294,8 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S @Override public final PingCommand getCurrentStatus(final long id) { - PingCommand pingCmd = new PingRoutingCommand(getType(), id, null); + // TODO, need to report VM states on host + PingCommand pingCmd = new PingRoutingCommand(getType(), id, null, null); if (s_logger.isDebugEnabled()) { s_logger.debug("Ping host " + _name + " (IP " + _agentIp + ")"); diff --git a/plugins/hypervisors/hyperv/test/com/cloud/hypervisor/hyperv/test/HypervDirectConnectResourceTest.java b/plugins/hypervisors/hyperv/test/com/cloud/hypervisor/hyperv/test/HypervDirectConnectResourceTest.java index 1f90da9aded..33694603f74 100644 --- a/plugins/hypervisors/hyperv/test/com/cloud/hypervisor/hyperv/test/HypervDirectConnectResourceTest.java +++ b/plugins/hypervisors/hyperv/test/com/cloud/hypervisor/hyperv/test/HypervDirectConnectResourceTest.java @@ -57,6 +57,7 @@ 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.HostVmStateReportEntry; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; @@ -298,7 +299,8 @@ public class HypervDirectConnectResourceTest { StartupRoutingCommand defaultStartRoutCmd = new StartupRoutingCommand( 0, 0, 0, 0, null, Hypervisor.HypervisorType.Hyperv, RouterPrivateIpStrategy.HostLocal, - new HashMap()); + new HashMap(), + new HashMap()); // Identity within the data centre is decided by CloudStack kernel, // and passed via ServerResource.configure() diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 775b2b898ea..50f43c0f670 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -59,6 +59,7 @@ import javax.naming.ConfigurationException; import com.cloud.agent.api.CheckOnHostCommand; import com.cloud.agent.api.routing.*; + import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import org.libvirt.Connect; @@ -69,7 +70,6 @@ import org.libvirt.DomainInterfaceStats; import org.libvirt.DomainSnapshot; import org.libvirt.LibvirtException; import org.libvirt.NodeInfo; - import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; @@ -112,6 +112,7 @@ import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.HostStatsEntry; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.MaintainAnswer; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.ManageSnapshotAnswer; @@ -236,8 +237,8 @@ import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.Script; import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.State; - import com.ceph.rados.Rados; import com.ceph.rados.RadosException; import com.ceph.rados.IoCTX; @@ -373,6 +374,8 @@ ServerResource { protected int _timeout; protected int _cmdsTimeout; protected int _stopTimeout; + + // TODO vmsync { protected static HashMap s_statesTable; static { s_statesTable = new HashMap(); @@ -389,6 +392,24 @@ ServerResource { s_statesTable.put(DomainInfo.DomainState.VIR_DOMAIN_SHUTDOWN, State.Stopping); } + // TODO vmsync } + + protected static HashMap s_powerStatesTable; + static { + s_powerStatesTable = new HashMap(); + s_powerStatesTable.put(DomainInfo.DomainState.VIR_DOMAIN_SHUTOFF, + PowerState.PowerOff); + s_powerStatesTable.put(DomainInfo.DomainState.VIR_DOMAIN_PAUSED, + PowerState.PowerOn); + s_powerStatesTable.put(DomainInfo.DomainState.VIR_DOMAIN_RUNNING, + PowerState.PowerOn); + s_powerStatesTable.put(DomainInfo.DomainState.VIR_DOMAIN_BLOCKED, + PowerState.PowerOn); + s_powerStatesTable.put(DomainInfo.DomainState.VIR_DOMAIN_NOSTATE, + PowerState.PowerUnknown); + s_powerStatesTable.put(DomainInfo.DomainState.VIR_DOMAIN_SHUTDOWN, + PowerState.PowerOff); + } protected HashMap _vms = new HashMap(20); protected List _vmsKilled = new ArrayList(); @@ -2814,6 +2835,11 @@ ServerResource { final State state = s_statesTable.get(ps); return state == null ? State.Unknown : state; } + + protected PowerState convertToPowerState(DomainInfo.DomainState ps) { + final PowerState state = s_powerStatesTable.get(ps); + return state == null ? PowerState.PowerUnknown : state; + } protected State getVmState(Connect conn, final String vmName) { int retry = 3; @@ -3962,10 +3988,10 @@ ServerResource { if (!_can_bridge_firewall) { return new PingRoutingCommand(com.cloud.host.Host.Type.Routing, id, - newStates); + newStates, this.getHostVmStateReport()); } else { HashMap> nwGrpStates = syncNetworkGroups(id); - return new PingRoutingWithNwGroupsCommand(getType(), id, newStates, + return new PingRoutingWithNwGroupsCommand(getType(), id, newStates, this.getHostVmStateReport(), nwGrpStates); } } @@ -4010,6 +4036,7 @@ ServerResource { cmd.setPool(_pool); cmd.setCluster(_clusterId); cmd.setGatewayIpAddress(_localGateway); + cmd.setHostVmStateReport(getHostVmStateReport()); StartupStorageCommand sscmd = null; try { @@ -4323,6 +4350,104 @@ ServerResource { return vmStates; } + + private HashMap getHostVmStateReport() { + final HashMap vmStates = new HashMap(); + Connect conn = null; + + if (_hypervisorType == HypervisorType.LXC) { + try { + conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString()); + vmStates.putAll(getHostVmStateReport(conn)); + } catch (LibvirtException e) { + s_logger.debug("Failed to get connection: " + e.getMessage()); + } + } + + if (_hypervisorType == HypervisorType.KVM) { + try { + conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString()); + vmStates.putAll(getHostVmStateReport(conn)); + } catch (LibvirtException e) { + s_logger.debug("Failed to get connection: " + e.getMessage()); + } + } + + return vmStates; + } + + private HashMap getHostVmStateReport(Connect conn) { + final HashMap vmStates = new HashMap(); + + String[] vms = null; + int[] ids = null; + + try { + ids = conn.listDomains(); + } catch (final LibvirtException e) { + s_logger.warn("Unable to listDomains", e); + return null; + } + try { + vms = conn.listDefinedDomains(); + } catch (final LibvirtException e) { + s_logger.warn("Unable to listDomains", e); + return null; + } + + Domain dm = null; + for (int i = 0; i < ids.length; i++) { + try { + dm = conn.domainLookupByID(ids[i]); + + DomainInfo.DomainState ps = dm.getInfo().state; + + final PowerState state = convertToPowerState(ps); + + s_logger.trace("VM " + dm.getName() + ": powerstate = " + ps + + "; vm state=" + state.toString()); + String vmName = dm.getName(); + vmStates.put(vmName, new HostVmStateReportEntry(state, conn.getHostName(), null)); + } catch (final LibvirtException e) { + s_logger.warn("Unable to get vms", e); + } finally { + try { + if (dm != null) { + dm.free(); + } + } catch (LibvirtException e) { + s_logger.trace("Ignoring libvirt error.", e); + } + } + } + + for (int i = 0; i < vms.length; i++) { + try { + + dm = conn.domainLookupByName(vms[i]); + + DomainInfo.DomainState ps = dm.getInfo().state; + final PowerState state = convertToPowerState(ps); + String vmName = dm.getName(); + s_logger.trace("VM " + vmName + ": powerstate = " + ps + + "; vm state=" + state.toString()); + + vmStates.put(vmName, new HostVmStateReportEntry(state, conn.getHostName(), null)); + } catch (final LibvirtException e) { + s_logger.warn("Unable to get vms", e); + } finally { + try { + if (dm != null) { + dm.free(); + } + } catch (LibvirtException e) { + s_logger.trace("Ignoring libvirt error.", e); + } + } + } + + return vmStates; + } protected List getHostInfo() { final ArrayList info = new ArrayList(); diff --git a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java index 2d0d67b2f41..32679c8ff13 100755 --- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java +++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java @@ -35,7 +35,6 @@ import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; import com.trilead.ssh2.SCPClient; - import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; @@ -61,6 +60,7 @@ import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.HostStatsEntry; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.MaintainAnswer; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateAnswer; @@ -131,6 +131,7 @@ import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SSHCmdHelper; import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.State; import com.trilead.ssh2.SCPClient; @@ -153,11 +154,12 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { boolean _canBridgeFirewall; static boolean _isHeartBeat = false; List _bridges = null; - protected HashMap _vms = new HashMap(50); - static HashMap _stateMaps; private final Map> _vmNetworkStats= new ConcurrentHashMap>(); private static String _ovsAgentPath = "/opt/ovs-agent-latest"; - + + // TODO vmsync { + static HashMap _stateMaps; + protected HashMap _vms = new HashMap(50); static { _stateMaps = new HashMap(); _stateMaps.put("RUNNING", State.Running); @@ -165,6 +167,16 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { _stateMaps.put("ERROR", State.Error); _stateMaps.put("SUSPEND", State.Stopped); } + // TODO vmsync } + + static HashMap _powerStateMaps; + static { + _powerStateMaps = new HashMap(); + _powerStateMaps.put("RUNNING", PowerState.PowerOn); + _powerStateMaps.put("DOWN", PowerState.PowerOff); + _powerStateMaps.put("ERROR", PowerState.PowerUnknown); + _powerStateMaps.put("SUSPEND", PowerState.PowerOff); + } @Override public boolean configure(String name, Map params) @@ -303,6 +315,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { //TODO: introudce PIF cmd.setPrivateIpAddress(_ip); cmd.setStorageIpAddress(_ip); + cmd.setHostVmStateReport(getHostVmStateReport()); String defaultBridge = OvmBridge.getBridgeByIp(_conn, _ip); if (_publicNetworkName == null) { @@ -397,7 +410,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { try { OvmHost.ping(_conn); HashMap newStates = sync(); - return new PingRoutingCommand(getType(), id, newStates); + return new PingRoutingCommand(getType(), id, newStates, this.getHostVmStateReport()); } catch (XmlRpcException e) { s_logger.debug("Check agent status failed", e); return null; @@ -785,6 +798,25 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { return state; } + private PowerState toPowerState(String vmName, String s) { + PowerState state = _powerStateMaps.get(s); + if (state == null) { + s_logger.debug("Unkown state " + s + " for " + vmName); + state = PowerState.PowerUnknown; + } + return state; + } + + protected HashMap getHostVmStateReport() throws XmlRpcException { + final HashMap vmStates = new HashMap(); + Map vms = OvmHost.getAllVms(_conn); + for (final Map.Entry entry : vms.entrySet()) { + PowerState state = toPowerState(entry.getKey(), entry.getValue()); + vmStates.put(entry.getKey(), new HostVmStateReportEntry(state, _conn.getIp(), null)); + } + return vmStates; + } + protected HashMap getAllVms() throws XmlRpcException { final HashMap vmStates = new HashMap(); Map vms = OvmHost.getAllVms(_conn); diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java index 9a27d748a29..727e067e527 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java @@ -29,6 +29,7 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckVirtualMachineAnswer; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; import com.cloud.agent.api.ReadyAnswer; @@ -53,6 +54,7 @@ import com.cloud.simulator.MockVMVO; import com.cloud.storage.Storage.StorageResourceType; import com.cloud.storage.template.TemplateProp; import com.cloud.utils.Pair; +import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.State; public class AgentRoutingResource extends AgentStorageResource { @@ -114,7 +116,7 @@ public class AgentRoutingResource extends AgentStorageResource { } final HashMap newStates = sync(); HashMap> nwGrpStates = _simMgr.syncNetworkGroups(hostGuid); - return new PingRoutingWithNwGroupsCommand(getType(), id, newStates, nwGrpStates); + return new PingRoutingWithNwGroupsCommand(getType(), id, newStates, getHostVmStateReport(), nwGrpStates); } @Override @@ -275,6 +277,18 @@ public class AgentRoutingResource extends AgentStorageResource { return info; } + + protected HashMap getHostVmStateReport() { + HashMap report = new HashMap(); + + for(String vmName : _runningVms.keySet()) { + report.put(vmName, new HostVmStateReportEntry(PowerState.PowerOn, agentHost.getName(), null)); + } + + + + return report; + } protected HashMap sync() { Map newStates; diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 03af0da51b1..26ef0475a83 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -46,6 +46,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import com.cloud.agent.api.routing.*; + import org.apache.log4j.Logger; import org.apache.log4j.NDC; @@ -161,6 +162,7 @@ import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.HostStatsEntry; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.MaintainAnswer; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.ManageSnapshotAnswer; @@ -301,6 +303,7 @@ import com.cloud.utils.net.NetUtils; import com.cloud.utils.ssh.SshHelper; import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VmDetailConstants; @@ -358,6 +361,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa protected StorageSubsystemCommandHandler storageHandler; + protected static HashMap s_powerStatesTable; + static { + s_powerStatesTable = new HashMap(); + s_powerStatesTable.put(VirtualMachinePowerState.POWERED_ON, PowerState.PowerOn); + s_powerStatesTable.put(VirtualMachinePowerState.POWERED_OFF, PowerState.PowerOff); + s_powerStatesTable.put(VirtualMachinePowerState.SUSPENDED, PowerState.PowerOn); + } + + // TODO vmsync { + // deprecated, will delete after full replacement + // protected static HashMap s_statesTable; static { s_statesTable = new HashMap(); @@ -365,6 +379,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_statesTable.put(VirtualMachinePowerState.POWERED_OFF, State.Stopped); s_statesTable.put(VirtualMachinePowerState.SUSPENDED, State.Stopped); } + // TODO vmsync } public Gson getGson() { return _gson; @@ -2559,7 +2574,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa long requestedMaxMemoryInMb = vmSpec.getMaxRam() / (1024 * 1024); // Check if VM is really running on hypervisor host - if (getVmState(vmMo) != State.Running) { + if (getVmPowerState(vmMo) != PowerState.PowerOn) { throw new CloudRuntimeException("Found that the VM " + vmMo.getVmName() + " is not running. Unable to scale-up this VM"); } @@ -2609,7 +2624,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa try { VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - // mark VM as starting state so that sync() can know not to report stopped too early + // mark VM as starting state so that sync can know not to report stopped too early synchronized (_vms) { _vms.put(vmInternalCSName, State.Starting); } @@ -2639,7 +2654,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa boolean hasSnapshot = false; if (vmMo != null) { s_logger.info("VM " + vmInternalCSName + " already exists, tear down devices for reconfiguration"); - if (getVmState(vmMo) != State.Stopped) + if (getVmPowerState(vmMo) != PowerState.PowerOff) vmMo.safePowerOff(_shutdown_waitMs); // retrieve disk information before we tear down @@ -2662,7 +2677,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa takeVmFromOtherHyperHost(hyperHost, vmInternalCSName); - if (getVmState(vmMo) != State.Stopped) + if (getVmPowerState(vmMo) != PowerState.PowerOff) vmMo.safePowerOff(_shutdown_waitMs); diskInfoBuilder = vmMo.getDiskInfoBuilder(); @@ -3885,7 +3900,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa try { vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, "0"); - if (getVmState(vmMo) != State.Stopped) { + if (getVmPowerState(vmMo) != PowerState.PowerOff) { if (vmMo.safePowerOff(_shutdown_waitMs)) { state = State.Stopped; return new StopAnswer(cmd, "Stop VM " + cmd.getVmName() + " Succeed", true); @@ -5488,7 +5503,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa List networks = vmMo.getNetworksWithDetails(); // tear down all devices first before we destroy the VM to avoid accidently delete disk backing files - if (getVmState(vmMo) != State.Stopped) + if (getVmPowerState(vmMo) != PowerState.PowerOff) vmMo.safePowerOff(_shutdown_waitMs); vmMo.tearDownDevices(new Class[] { /* VirtualDisk.class, */ VirtualEthernetCard.class }); vmMo.destroy(); @@ -5813,86 +5828,85 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa @Override public PingCommand getCurrentStatus(long id) { - try { - HashMap newStates = sync(); - if (newStates == null) { - return null; - } - - try { - // take the chance to do left-over dummy VM cleanup from previous run - VmwareContext context = getServiceContext(); - VmwareHypervisorHost hyperHost = getHyperHost(context); - VmwareManager mgr = hyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - - if(hyperHost.isHyperHostConnected()) { - mgr.gcLeftOverVMs(context); - - s_logger.info("Scan hung worker VM to recycle"); - - int workerKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER); - int workerTagKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER_TAG); - String workerPropName = String.format("value[%d]", workerKey); - String workerTagPropName = String.format("value[%d]", workerTagKey); + gcAndKillHungWorkerVMs(); + + HashMap newStates = sync(); + if (newStates == null) { + return null; + } + return new PingRoutingCommand(getType(), id, newStates, syncHostVmStates()); + } + + private void gcAndKillHungWorkerVMs() { + try { + // take the chance to do left-over dummy VM cleanup from previous run + VmwareContext context = getServiceContext(); + VmwareHypervisorHost hyperHost = getHyperHost(context); + VmwareManager mgr = hyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - // GC worker that has been running for too long - ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost( - new String[] {"name", "config.template", workerPropName, workerTagPropName, - }); - if(ocs != null) { - for(ObjectContent oc : ocs) { - List props = oc.getPropSet(); - if(props != null) { - boolean template = false; - boolean isWorker = false; - String workerTag = null; + if(hyperHost.isHyperHostConnected()) { + mgr.gcLeftOverVMs(context); - for(DynamicProperty prop : props) { - if(prop.getName().equals("config.template")) { - template = (Boolean)prop.getVal(); - } else if(prop.getName().equals(workerPropName)) { - CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal(); - if(val != null && val.getValue() != null && val.getValue().equalsIgnoreCase("true")) - isWorker = true; - } - else if(prop.getName().equals(workerTagPropName)) { - CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal(); - workerTag = val.getValue(); - } + s_logger.info("Scan hung worker VM to recycle"); + + int workerKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER); + int workerTagKey = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_WORKER_TAG); + String workerPropName = String.format("value[%d]", workerKey); + String workerTagPropName = String.format("value[%d]", workerTagKey); + + // GC worker that has been running for too long + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost( + new String[] {"name", "config.template", workerPropName, workerTagPropName, + }); + if(ocs != null) { + for(ObjectContent oc : ocs) { + List props = oc.getPropSet(); + if(props != null) { + boolean template = false; + boolean isWorker = false; + String workerTag = null; + + for(DynamicProperty prop : props) { + if(prop.getName().equals("config.template")) { + template = (Boolean)prop.getVal(); + } else if(prop.getName().equals(workerPropName)) { + CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal(); + if(val != null && val.getValue() != null && val.getValue().equalsIgnoreCase("true")) + isWorker = true; } + else if(prop.getName().equals(workerTagPropName)) { + CustomFieldStringValue val = (CustomFieldStringValue)prop.getVal(); + workerTag = val.getValue(); + } + } - VirtualMachineMO vmMo = new VirtualMachineMO(hyperHost.getContext(), oc.getObj()); - if(!template && isWorker) { - boolean recycle = false; - recycle = mgr.needRecycle(workerTag); + VirtualMachineMO vmMo = new VirtualMachineMO(hyperHost.getContext(), oc.getObj()); + if(!template && isWorker) { + boolean recycle = false; + recycle = mgr.needRecycle(workerTag); - if(recycle) { - s_logger.info("Recycle pending worker VM: " + vmMo.getName()); + if(recycle) { + s_logger.info("Recycle pending worker VM: " + vmMo.getName()); - vmMo.powerOff(); - vmMo.destroy(); - } + vmMo.powerOff(); + vmMo.destroy(); } } } - } - } else { - s_logger.error("Host is no longer connected."); - return null; - } - } catch (Throwable e) { - if (e instanceof RemoteException) { - s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); - invalidateServiceContext(); - return null; - } - } - - return new PingRoutingCommand(getType(), id, newStates); + } + } + } else { + s_logger.error("Host is no longer connected."); + } - } finally { - recycleServiceContext(); - } + } catch (Throwable e) { + if (e instanceof RemoteException) { + s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); + invalidateServiceContext(); + } + } finally { + recycleServiceContext(); + } } @Override @@ -5935,7 +5949,14 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } cmd.setHypervisorType(HypervisorType.VMware); + + // TODO vmsync { + // deprecated after full replacement cmd.setStateChanges(changes); + // TODO vmsync} + + cmd.setHostVmStateReport(syncHostVmStates()); + cmd.setCluster(_cluster); cmd.setHypervisorVersion(hostApiVersion); @@ -6091,6 +6112,14 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } + protected HashMap syncHostVmStates() { + try { + return getHostVmStateReport(); + } catch(Exception e) { + return new HashMap(); + } + } + protected HashMap sync() { HashMap changes = new HashMap(); HashMap oldStates = null; @@ -6295,6 +6324,65 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return VirtualMachineGuestOsIdentifier.OTHER_GUEST; } + private HashMap getHostVmStateReport() throws Exception { + VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); + + int key = ((HostMO)hyperHost).getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); + if(key == 0) { + s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); + } + String instanceNameCustomField = "value[" + key + "]"; + + // CLOUD_VM_INTERNAL_NAME stores the internal CS generated vm name. This was earlier stored in name. Now, name can be either the hostname or + // the internal CS name, but the custom field CLOUD_VM_INTERNAL_NAME always stores the internal CS name. + ObjectContent[] ocs = hyperHost.getVmPropertiesOnHyperHost( + new String[] { "name", "runtime.powerState", "config.template", instanceNameCustomField } + ); + + HashMap newStates = new HashMap(); + if (ocs != null && ocs.length > 0) { + for (ObjectContent oc : ocs) { + List objProps = oc.getPropSet(); + if (objProps != null) { + + boolean isTemplate = false; + String name = null; + String VMInternalCSName = null; + VirtualMachinePowerState powerState = VirtualMachinePowerState.POWERED_OFF; + for (DynamicProperty objProp : objProps) { + if (objProp.getName().equals("config.template")) { + if (objProp.getVal().toString().equalsIgnoreCase("true")) { + isTemplate = true; + } + } else if (objProp.getName().equals("runtime.powerState")) { + powerState = (VirtualMachinePowerState) objProp.getVal(); + } else if (objProp.getName().equals("name")) { + name = (String) objProp.getVal(); + } else if(objProp.getName().contains(instanceNameCustomField)) { + if(objProp.getVal() != null) + VMInternalCSName = ((CustomFieldStringValue)objProp.getVal()).getValue(); + } + else { + assert (false); + } + } + + if (VMInternalCSName != null) + name = VMInternalCSName; + + if (!isTemplate) { + newStates.put( + name, + new HostVmStateReportEntry(convertPowerState(powerState), hyperHost.getHyperHostName(), null) + ); + } + } + } + } + return newStates; + } + + // TODO vmsync { private HashMap getVmStates() throws Exception { VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); @@ -6462,6 +6550,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } return vmResponseMap; } + // TODO vmsync } protected String networkUsage(final String privateIpAddress, final String option, final String ethName) { String args = null; @@ -6572,6 +6661,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return connect(vmname, ipAddress, 3922); } + // TODO vmsync { + // deprecated after full replacement private static State convertState(VirtualMachinePowerState powerState) { return s_statesTable.get(powerState); } @@ -6580,7 +6671,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa VirtualMachineRuntimeInfo runtimeInfo = vmMo.getRuntimeInfo(); return convertState(runtimeInfo.getPowerState()); } + // TODO vmsync } + + private static PowerState convertPowerState(VirtualMachinePowerState powerState) { + return s_powerStatesTable.get(powerState); + } + public static PowerState getVmPowerState(VirtualMachineMO vmMo) throws Exception { + VirtualMachineRuntimeInfo runtimeInfo = vmMo.getRuntimeInfo(); + return convertPowerState(runtimeInfo.getPowerState()); + } + private static HostStatsEntry getHyperHostStats(VmwareHypervisorHost hyperHost) throws Exception { ComputeResourceSummary hardwareSummary = hyperHost.getHyperHostHardwareSummary(); if(hardwareSummary == null) diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 69b7c9e07c7..aadfc17936a 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -63,6 +63,7 @@ import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.HostStatsEntry; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.MaintainAnswer; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.ManageSnapshotAnswer; @@ -188,6 +189,7 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.DiskProfile; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.snapshot.VMSnapshot; import com.google.gson.Gson; @@ -225,6 +227,7 @@ import com.xensource.xenapi.VLAN; import com.xensource.xenapi.VM; import com.xensource.xenapi.VMGuestMetrics; import com.xensource.xenapi.XenAPIObject; + import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; @@ -239,6 +242,7 @@ import org.xml.sax.InputSource; import javax.ejb.Local; import javax.naming.ConfigurationException; import javax.xml.parsers.DocumentBuilderFactory; + import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -347,6 +351,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } + protected static HashMap s_powerStatesTable; + static { + s_powerStatesTable = new HashMap(); + s_powerStatesTable.put(Types.VmPowerState.HALTED, PowerState.PowerOff); + s_powerStatesTable.put(Types.VmPowerState.PAUSED, PowerState.PowerOn); + s_powerStatesTable.put(Types.VmPowerState.RUNNING, PowerState.PowerOn); + s_powerStatesTable.put(Types.VmPowerState.SUSPENDED, PowerState.PowerOn); + s_powerStatesTable.put(Types.VmPowerState.UNRECOGNIZED, PowerState.PowerUnknown); + } + + // TODO vmsync { protected static HashMap s_statesTable; static { s_statesTable = new HashMap(); @@ -356,6 +371,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_statesTable.put(Types.VmPowerState.SUSPENDED, State.Running); s_statesTable.put(Types.VmPowerState.UNRECOGNIZED, State.Unknown); } + // TODO vmsync } public XsHost getHost() { return _host; @@ -2975,7 +2991,61 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe final State state = s_statesTable.get(ps); return state == null ? State.Unknown : state; } + + private static PowerState convertPowerState(Types.VmPowerState powerState) { + return s_powerStatesTable.get(powerState); + } + protected HashMap getHostVmStateReport(Connection conn) { + final HashMap vmStates = new HashMap(); + Map vm_map = null; + for (int i = 0; i < 2; i++) { + try { + vm_map = VM.getAllRecords(conn); //USE THIS TO GET ALL VMS FROM A CLUSTER + break; + } catch (final Throwable e) { + s_logger.warn("Unable to get vms", e); + } + try { + Thread.sleep(1000); + } catch (final InterruptedException ex) { + + } + } + + if (vm_map == null) { + return null; + } + for (VM.Record record: vm_map.values()) { + if (record.isControlDomain || record.isASnapshot || record.isATemplate) { + continue; // Skip DOM0 + } + + VmPowerState ps = record.powerState; + Host host = record.residentOn; + String xstoolsversion = getVMXenToolsVersion(record.platform); + String host_uuid = null; + if( ! isRefNull(host) ) { + try { + host_uuid = host.getUuid(conn); + } catch (BadServerResponse e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } catch (XenAPIException e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } catch (XmlRpcException e) { + s_logger.error("Failed to get host uuid for host " + host.toWireString(), e); + } + vmStates.put( + record.nameLabel, + new HostVmStateReportEntry(convertPowerState(ps), host_uuid, xstoolsversion) + ); + } + } + + return vmStates; + } + + // TODO vmsync { protected HashMap> getAllVms(Connection conn) { final HashMap> vmStates = new HashMap>(); Map vm_map = null; @@ -3025,6 +3095,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return vmStates; } + // TODO vmsync } protected State getVmState(Connection conn, final String vmName) { int retry = 3; @@ -4749,13 +4820,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } Connection conn = getConnection(); if (!_canBridgeFirewall && !_isOvs) { - return new PingRoutingCommand(getType(), id, null); + return new PingRoutingCommand(getType(), id, null, getHostVmStateReport(conn)); } else if (_isOvs) { List>ovsStates = ovsFullSyncStates(); - return new PingRoutingWithOvsCommand(getType(), id, null, ovsStates); + return new PingRoutingWithOvsCommand(getType(), id, null, getHostVmStateReport(conn), ovsStates); }else { HashMap> nwGrpStates = syncNetworkGroups(conn, id); - return new PingRoutingWithNwGroupsCommand(getType(), id, null, nwGrpStates); + return new PingRoutingWithNwGroupsCommand(getType(), id, null, getHostVmStateReport(conn), nwGrpStates); } } catch (Exception e) { s_logger.warn("Unable to get current status", e); @@ -5010,6 +5081,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe cmd.setHypervisorType(HypervisorType.XenServer); cmd.setCluster(_cluster); cmd.setPoolSync(false); + cmd.setHostVmStateReport(this.getHostVmStateReport(conn)); Pool pool; try { diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/KvmDummyResourceBase.java b/server/src/com/cloud/hypervisor/kvm/discoverer/KvmDummyResourceBase.java index 240ea6ce316..d6fde31833d 100644 --- a/server/src/com/cloud/hypervisor/kvm/discoverer/KvmDummyResourceBase.java +++ b/server/src/com/cloud/hypervisor/kvm/discoverer/KvmDummyResourceBase.java @@ -23,6 +23,7 @@ import javax.naming.ConfigurationException; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; @@ -46,7 +47,9 @@ public class KvmDummyResourceBase extends ServerResourceBase implements ServerRe @Override public StartupCommand[] initialize() { - StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.KVM, new HashMap(), new HashMap()); + StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.KVM, + new HashMap(), new HashMap(), + new HashMap()); cmd.setDataCenter(_zoneId); cmd.setPod(_podId); cmd.setCluster(_clusterId); diff --git a/server/src/com/cloud/resource/DummyHostServerResource.java b/server/src/com/cloud/resource/DummyHostServerResource.java index 977dbbf6e19..1d58c80d221 100644 --- a/server/src/com/cloud/resource/DummyHostServerResource.java +++ b/server/src/com/cloud/resource/DummyHostServerResource.java @@ -23,6 +23,7 @@ import javax.naming.ConfigurationException; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.StartupCommand; @@ -57,7 +58,8 @@ public class DummyHostServerResource extends ServerResourceBase { @Override public PingCommand getCurrentStatus(long id) { HashMap newStates = new HashMap(); - return new PingRoutingCommand(com.cloud.host.Host.Type.Routing, id, newStates); + return new PingRoutingCommand(com.cloud.host.Host.Type.Routing, id, newStates, + new HashMap()); } @Override diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index 784c0316e04..108e35a5cdf 100644 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -180,7 +180,7 @@ public class VirtualMachineMO extends BaseMO { } public boolean powerOn() throws Exception { - if(getPowerState() == VirtualMachinePowerState.POWERED_ON) + if(getResetSafePowerState() == VirtualMachinePowerState.POWERED_ON) return true; ManagedObjectReference morTask = _context.getService().powerOnVMTask(_mor, null); @@ -197,7 +197,7 @@ public class VirtualMachineMO extends BaseMO { } public boolean powerOff() throws Exception { - if(getPowerState() == VirtualMachinePowerState.POWERED_OFF) + if(getResetSafePowerState() == VirtualMachinePowerState.POWERED_OFF) return true; return powerOffNoCheck(); @@ -205,7 +205,7 @@ public class VirtualMachineMO extends BaseMO { public boolean safePowerOff(int shutdownWaitMs) throws Exception { - if(getPowerState() == VirtualMachinePowerState.POWERED_OFF) + if(getResetSafePowerState() == VirtualMachinePowerState.POWERED_OFF) return true; if(isVMwareToolsRunning()) { @@ -216,14 +216,14 @@ public class VirtualMachineMO extends BaseMO { shutdown(); long startTick = System.currentTimeMillis(); - while(getPowerState() != VirtualMachinePowerState.POWERED_OFF && System.currentTimeMillis() - startTick < shutdownWaitMs) { + while(getResetSafePowerState() != VirtualMachinePowerState.POWERED_OFF && System.currentTimeMillis() - startTick < shutdownWaitMs) { try { Thread.sleep(1000); } catch(InterruptedException e) { } } - if(getPowerState() != VirtualMachinePowerState.POWERED_OFF) { + if(getResetSafePowerState() != VirtualMachinePowerState.POWERED_OFF) { s_logger.info("can not gracefully shutdown VM within " + (shutdownWaitMs/1000) + " seconds, we will perform force power off on VM " + vmName); return powerOffNoCheck(); } @@ -248,7 +248,7 @@ public class VirtualMachineMO extends BaseMO { // wait up to 5 seconds to make sure to avoid race conditioning for immediate following on operations // that relies on a powered-off VM long startTick = System.currentTimeMillis(); - while(getPowerState() != VirtualMachinePowerState.POWERED_OFF && System.currentTimeMillis() - startTick < 5000) { + while(getResetSafePowerState() != VirtualMachinePowerState.POWERED_OFF && System.currentTimeMillis() - startTick < 5000) { try { Thread.sleep(1000); } catch(InterruptedException e) { @@ -256,7 +256,7 @@ public class VirtualMachineMO extends BaseMO { } return true; } else { - if(getPowerState() == VirtualMachinePowerState.POWERED_OFF) { + if(getResetSafePowerState() == VirtualMachinePowerState.POWERED_OFF) { // to help deal with possible race-condition s_logger.info("Current power-off task failed. However, VM has been switched to the state we are expecting for"); return true; @@ -268,7 +268,7 @@ public class VirtualMachineMO extends BaseMO { return false; } - public VirtualMachinePowerState getPowerState() throws Exception { + public VirtualMachinePowerState getResetSafePowerState() throws Exception { VirtualMachinePowerState powerState = VirtualMachinePowerState.POWERED_OFF; @@ -293,6 +293,10 @@ public class VirtualMachineMO extends BaseMO { return powerState; } + + public VirtualMachinePowerState getPowerState() throws Exception { + return (VirtualMachinePowerState)getContext().getVimClient().getDynamicProperty(_mor, "runtime.powerState"); + } public boolean reset() throws Exception { ManagedObjectReference morTask = _context.getService().resetVMTask(_mor);