diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index c48515d2f07..b6ccd7724e2 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -40,7 +40,9 @@ public interface VirtualMachine extends RunningOn, ControlledEntity { Expunging(true, "VM is being expunged."), Migrating(true, "VM is being migrated. host id holds to from host"), Error(false, "VM is in error"), - Unknown(false, "VM state is unknown."); + Unknown(false, "VM state is unknown."), + Shutdowned(false, "VM is shutdowned from inside"); + private final boolean _transitional; String _description; @@ -82,40 +84,45 @@ public interface VirtualMachine extends RunningOn, ControlledEntity { protected static final StateMachine s_fsm = new StateMachine(); static { - s_fsm.addTransition(null, VirtualMachine.Event.CreateRequested, State.Creating); - s_fsm.addTransition(State.Creating, VirtualMachine.Event.OperationSucceeded, State.Stopped); - s_fsm.addTransition(State.Creating, VirtualMachine.Event.OperationFailed, State.Error); - s_fsm.addTransition(State.Stopped, VirtualMachine.Event.StartRequested, State.Starting); - s_fsm.addTransition(State.Stopped, VirtualMachine.Event.DestroyRequested, State.Destroyed); - s_fsm.addTransition(State.Error, VirtualMachine.Event.DestroyRequested, State.Destroyed); - s_fsm.addTransition(State.Stopped, VirtualMachine.Event.StopRequested, State.Stopped); - s_fsm.addTransition(State.Stopped, VirtualMachine.Event.AgentReportStopped, State.Stopped); - s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationRetry, State.Starting); - s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationSucceeded, State.Running); - s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationFailed, State.Stopped); - s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportRunning, State.Running); - s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportStopped, State.Stopped); - s_fsm.addTransition(State.Destroyed, VirtualMachine.Event.RecoveryRequested, State.Stopped); - s_fsm.addTransition(State.Destroyed, VirtualMachine.Event.ExpungeOperation, State.Expunging); - s_fsm.addTransition(State.Creating, VirtualMachine.Event.MigrationRequested, State.Destroyed); - s_fsm.addTransition(State.Running, VirtualMachine.Event.MigrationRequested, State.Migrating); - s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportRunning, State.Running); - s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportStopped, State.Stopped); - s_fsm.addTransition(State.Running, VirtualMachine.Event.StopRequested, State.Stopping); - s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationRequested, State.Migrating); - s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationSucceeded, State.Running); - s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationFailed, State.Running); - s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationFailedOnSource, State.Running); - s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationFailedOnDest, State.Running); - s_fsm.addTransition(State.Migrating, VirtualMachine.Event.AgentReportRunning, State.Running); - s_fsm.addTransition(State.Migrating, VirtualMachine.Event.AgentReportStopped, State.Stopped); - s_fsm.addTransition(State.Stopping, VirtualMachine.Event.OperationSucceeded, State.Stopped); - s_fsm.addTransition(State.Stopping, VirtualMachine.Event.OperationFailed, State.Running); - s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportRunning, State.Running); - s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportStopped, State.Stopped); - s_fsm.addTransition(State.Stopping, VirtualMachine.Event.StopRequested, State.Stopping); - s_fsm.addTransition(State.Expunging, VirtualMachine.Event.OperationFailed, State.Expunging); - s_fsm.addTransition(State.Expunging, VirtualMachine.Event.ExpungeOperation, State.Expunging); + s_fsm.addTransition(null, VirtualMachine.Event.CreateRequested, State.Creating); + s_fsm.addTransition(State.Creating, VirtualMachine.Event.OperationSucceeded, State.Stopped); + s_fsm.addTransition(State.Creating, VirtualMachine.Event.OperationFailed, State.Error); + s_fsm.addTransition(State.Stopped, VirtualMachine.Event.StartRequested, State.Starting); + s_fsm.addTransition(State.Stopped, VirtualMachine.Event.DestroyRequested, State.Destroyed); + s_fsm.addTransition(State.Error, VirtualMachine.Event.DestroyRequested, State.Destroyed); + s_fsm.addTransition(State.Stopped, VirtualMachine.Event.StopRequested, State.Stopped); + s_fsm.addTransition(State.Stopped, VirtualMachine.Event.AgentReportStopped, State.Stopped); + s_fsm.addTransition(State.Stopped, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationRetry, State.Starting); + s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationSucceeded, State.Running); + s_fsm.addTransition(State.Starting, VirtualMachine.Event.OperationFailed, State.Stopped); + s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportRunning, State.Running); + s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportStopped, State.Stopped); + s_fsm.addTransition(State.Starting, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Destroyed, VirtualMachine.Event.RecoveryRequested, State.Stopped); + s_fsm.addTransition(State.Destroyed, VirtualMachine.Event.ExpungeOperation, State.Expunging); + s_fsm.addTransition(State.Creating, VirtualMachine.Event.MigrationRequested, State.Destroyed); + s_fsm.addTransition(State.Running, VirtualMachine.Event.MigrationRequested, State.Migrating); + s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportRunning, State.Running); + s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportStopped, State.Stopped); + s_fsm.addTransition(State.Running, VirtualMachine.Event.StopRequested, State.Stopping); + s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationRequested, State.Migrating); + s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationSucceeded, State.Running); + s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationFailed, State.Running); + s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationFailedOnSource, State.Running); + s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationFailedOnDest, State.Running); + s_fsm.addTransition(State.Migrating, VirtualMachine.Event.AgentReportRunning, State.Running); + s_fsm.addTransition(State.Migrating, VirtualMachine.Event.AgentReportStopped, State.Stopped); + s_fsm.addTransition(State.Migrating, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Stopping, VirtualMachine.Event.OperationSucceeded, State.Stopped); + s_fsm.addTransition(State.Stopping, VirtualMachine.Event.OperationFailed, State.Running); + s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportRunning, State.Running); + s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportStopped, State.Stopped); + s_fsm.addTransition(State.Stopping, VirtualMachine.Event.StopRequested, State.Stopping); + s_fsm.addTransition(State.Stopping, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Expunging, VirtualMachine.Event.OperationFailed, State.Expunging); + s_fsm.addTransition(State.Expunging, VirtualMachine.Event.ExpungeOperation, State.Expunging); } } @@ -134,7 +141,8 @@ public interface VirtualMachine extends RunningOn, ControlledEntity { MigrationFailedOnSource, MigrationFailedOnDest, OperationRetry, - OperationCancelled + OperationCancelled, + AgentReportShutdowned }; public enum Type { diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 26109962265..9b0d0b1373d 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -2368,12 +2368,22 @@ public abstract class CitrixResourceBase implements ServerResource { } else if (oldState == State.Migrating) { s_logger.debug("Ignoring VM " + vm + " in migrating state."); } else { - State state = State.Stopped; + State newState = State.Stopped; + try { + Set missingVMs = VM.getByNameLabel(conn, vm); + if( missingVMs != null && !missingVMs.isEmpty()) { + String shutdownInitiator = missingVMs.iterator().next().getOtherConfig(conn).get("last_shutdown_initiator"); + if( shutdownInitiator != null && shutdownInitiator.equals("internal")) { + newState = State.Shutdowned; + } + } + } catch (Exception e) { + } /* * if (_vmsKilled.remove(entry.getKey())) { s_logger.debug("VM " + vm + * " has been killed by storage monitor"); state = State.Error; } */ - changes.put(entry.getKey(), state); + changes.put(entry.getKey(), newState); } } } diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java index 5e7c2a68eb4..436a14ae988 100644 --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -527,8 +527,13 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager { } return null; } - - if (agentState == State.Stopped) { + if (agentState == State.Shutdowned ) { + if ( serverState == State.Running || serverState == State.Starting || serverState == State.Stopping ) { + _itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportShutdowned, null); + } + s_logger.debug("Sending cleanup to a shutdowned vm: " + agentName); + command = info.mgr.cleanup(vm, agentName); + } else if (agentState == State.Stopped) { // This state means the VM on the agent was detected previously // and now is gone. This is slightly different than if the VM // was never completed but we still send down a Stop Command