diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index 8ea04c9ca0b..82b09762016 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -72,12 +72,14 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject s_fsm.addTransition(State.Stopped, VirtualMachine.Event.OperationFailed, State.Error); s_fsm.addTransition(State.Stopped, VirtualMachine.Event.ExpungeOperation, State.Expunging); s_fsm.addTransition(State.Stopped, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); + s_fsm.addTransition(State.Stopped, VirtualMachine.Event.AgentReportMigrated, 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.Starting, VirtualMachine.Event.AgentReportMigrated, State.Starting); s_fsm.addTransition(State.Destroyed, VirtualMachine.Event.RecoveryRequested, State.Stopped); s_fsm.addTransition(State.Destroyed, VirtualMachine.Event.ExpungeOperation, State.Expunging); s_fsm.addTransition(State.Running, VirtualMachine.Event.MigrationRequested, State.Migrating); @@ -85,6 +87,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject 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.Running, VirtualMachine.Event.AgentReportMigrated, State.Running); 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); @@ -97,6 +100,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject 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.Stopping, VirtualMachine.Event.AgentReportMigrated, 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(State.Error, VirtualMachine.Event.DestroyRequested, State.Expunging); @@ -138,7 +142,8 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject OperationSucceeded, OperationFailed, OperationRetry, - AgentReportShutdowned + AgentReportShutdowned, + AgentReportMigrated }; public enum Type { diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 994b4c7ea68..c617125fce9 100644 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -519,10 +519,14 @@ public class CapacityManagerImpl implements CapacityManager, StateListener vmGuru = getVmGuru(vm); - Command command = null; if (s_logger.isDebugEnabled()) { @@ -1512,6 +1510,16 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene _alertMgr.sendAlert(alertType, vm.getDataCenterIdToDeployIn(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getInstanceName() + ", id: " + vm.getId() + ") stopped on host " + hostDesc + " due to storage failure", "Virtual Machine " + vm.getInstanceName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + "] stopped due to storage failure."); } + + if(trackExternalChange) { + if(hostId != vm.getHostId()) { + try { + stateTransitTo(vm, VirtualMachine.Event.AgentReportMigrated, hostId); + } catch (NoTransitionException e) { + s_logger.warn(e.getMessage()); + } + } + } // if (serverState == State.Migrating) { // s_logger.debug("Skipping vm in migrating state: " + vm); @@ -1525,17 +1533,14 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene assert (agentState == State.Stopped || agentState == State.Running) : "If the states we send up is changed, this must be changed."; if (agentState == State.Running) { try { - if(nativeHA) { - stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, hostId); - } else { - stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, vm.getHostId()); - } + stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, hostId); } catch (NoTransitionException e) { s_logger.warn(e.getMessage()); } // FIXME: What if someone comes in and sets it to stopping? Then what? return null; } + s_logger.debug("State matches but the agent said stopped so let's send a cleanup command anyways."); return cleanup(agentName); } @@ -1567,7 +1572,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene // Our records showed that it should be running so let's restart it. _haMgr.scheduleRestart(vm, false); } else if (serverState == State.Stopping) { - _haMgr.scheduleStop(vm, vm.getHostId(), WorkType.ForceStop); + _haMgr.scheduleStop(vm, hostId, WorkType.ForceStop); s_logger.debug("Scheduling a check stop for VM in stopping mode: " + vm); } else if (serverState == State.Starting) { s_logger.debug("Ignoring VM in starting mode: " + vm.getInstanceName()); @@ -1577,59 +1582,21 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene } else if (agentState == State.Running) { if (serverState == State.Starting) { if (fullSync) { - s_logger.debug("VM state is starting on full sync so updating it to running"); - vm = findById(vm.getType(), vm.getId()); - try { - stateTransitTo(vm, Event.AgentReportRunning, vm.getHostId()); - } catch (NoTransitionException e1) { - s_logger.warn(e1.getMessage()); - } - s_logger.debug("VM's " + vm + " state is starting on full sync so updating it to Running"); - vm = vmGuru.findById(vm.getId()); - - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); - List nics = _nicsDao.listByVmId(profile.getId()); - for (NicVO nic : nics) { - Network network = _networkMgr.getNetwork(nic.getNetworkId()); - NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null); - profile.addNic(nicProfile); - } - - Commands cmds = new Commands(OnError.Stop); - s_logger.debug("Finalizing commands that need to be send to complete Start process for the vm " + vm); - - if (vmGuru.finalizeCommandsOnStart(cmds, profile)) { - if (cmds.size() != 0) { - try { - _agentMgr.send(vm.getHostId(), cmds); - } catch (OperationTimedoutException e) { - s_logger.error("Exception during update for running vm: " + vm, e); - return null; - } catch (ResourceUnavailableException e) { - s_logger.error("Exception during update for running vm: " + vm, e); - return null; - } - } - - if (vmGuru.finalizeStart(profile, vm.getHostId(), cmds, null)) { - try { - stateTransitTo(vm, Event.AgentReportRunning, vm.getHostId()); - } catch (NoTransitionException e) { - s_logger.warn(e.getMessage()); - } - } else { - s_logger.error("Exception during update for running vm: " + vm); - return null; - } - } else { - s_logger.error("Unable to finalize commands on start for vm: " + vm); + try { + ensureVmRunningContext(hostId, vm, Event.AgentReportRunning); + } catch (OperationTimedoutException e) { + s_logger.error("Exception during update for running vm: " + vm, e); return null; + } catch (ResourceUnavailableException e) { + s_logger.error("Exception during update for running vm: " + vm, e); + return null; + } catch (NoTransitionException e) { + s_logger.warn(e.getMessage()); } - } } else if (serverState == State.Stopping) { s_logger.debug("Scheduling a stop command for " + vm); - _haMgr.scheduleStop(vm, vm.getHostId(), WorkType.Stop); + _haMgr.scheduleStop(vm, hostId, WorkType.Stop); } else { s_logger.debug("VM state is in stopped so stopping it on the agent"); command = cleanup(agentName); @@ -1637,6 +1604,46 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene } return command; } + + private void ensureVmRunningContext(long hostId, VMInstanceVO vm, Event cause) throws OperationTimedoutException, ResourceUnavailableException, NoTransitionException { + VirtualMachineGuru vmGuru = getVmGuru(vm); + + s_logger.debug("VM state is starting on full sync so updating it to running"); + vm = findById(vm.getType(), vm.getId()); + try { + stateTransitTo(vm, cause, hostId); + } catch (NoTransitionException e1) { + s_logger.warn(e1.getMessage()); + } + + s_logger.debug("VM's " + vm + " state is starting on full sync so updating it to Running"); + vm = vmGuru.findById(vm.getId()); // this should ensure vm has the most up to date info + + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + List nics = _nicsDao.listByVmId(profile.getId()); + for (NicVO nic : nics) { + Network network = _networkMgr.getNetwork(nic.getNetworkId()); + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null); + profile.addNic(nicProfile); + } + + Commands cmds = new Commands(OnError.Stop); + s_logger.debug("Finalizing commands that need to be send to complete Start process for the vm " + vm); + + if (vmGuru.finalizeCommandsOnStart(cmds, profile)) { + if (cmds.size() != 0) { + _agentMgr.send(vm.getHostId(), cmds); + } + + if (vmGuru.finalizeStart(profile, vm.getHostId(), cmds, null)) { + stateTransitTo(vm, cause, vm.getHostId()); + } else { + s_logger.error("Unable to finish finialization for running vm: " + vm); + } + } else { + s_logger.error("Unable to finalize commands on start for vm: " + vm); + } + } public Commands fullSync(final long hostId, final Map newStates) { Commands commands = new Commands(OnError.Continue);