diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index 3761a9f95d6..545d6065a42 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -210,6 +210,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject * @return id of the host it was assigned last time. */ public Long getLastHostId(); + public Long getHostId(); public void setLastHostId(Long lastHostId); diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 38bcd61b80e..14afd5e86f1 100644 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -29,9 +29,16 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import com.cloud.agent.Listener; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.AgentControlCommand; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.StartupCommand; import com.cloud.capacity.dao.CapacityDao; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.exception.ConnectionException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; @@ -46,12 +53,15 @@ import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; +import com.cloud.utils.fsm.StateListener; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.Event; +import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.VMInstanceDao; @Local(value=CapacityManager.class) -public class CapacityManagerImpl implements CapacityManager { +public class CapacityManagerImpl implements CapacityManager , StateListener{ private static final Logger s_logger = Logger.getLogger(CapacityManagerImpl.class); String _name; @Inject CapacityDao _capacityDao; @@ -59,6 +69,7 @@ public class CapacityManagerImpl implements CapacityManager { @Inject ServiceOfferingDao _offeringsDao; @Inject HostDao _hostDao; @Inject VMInstanceDao _vmDao; + private int _hostCapacityCheckerDelay; private int _hostCapacityCheckerInterval; private int _vmCapacityReleaseInterval; @@ -73,6 +84,7 @@ public class CapacityManagerImpl implements CapacityManager { _hostCapacityCheckerInterval = NumbersUtil.parseInt(_configDao.getValue(Config.HostCapacityCheckerInterval.key()), 3600); _vmCapacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.VmHostCapacityReleaseInterval.key()), 86400); _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("HostCapacity-Checker")); + VirtualMachine.State.getStateMachine().registerListener(this); return true; } @@ -330,4 +342,55 @@ public class CapacityManagerImpl implements CapacityManager { } } } + + @Override + public boolean preStateTransitionEvent(State oldState, + Event event, State newState, VirtualMachine vm, boolean transitionStatus, Long id) { + return true; + } + + @Override + public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vm, boolean status, Long oldHostId) { + s_logger.debug("VM state transitted from :" + oldState + " to " + newState + " with event: " + event + + "vm's original host id: " + vm.getLastHostId() + " new host id: " + vm.getHostId()); + if (!status) { + return false; + } + + if (oldState == State.Starting) { + if (event == Event.OperationFailed) { + releaseVmCapacity(vm, false, false, oldHostId); + } else if (event == Event.OperationRetry) { + releaseVmCapacity(vm, false, false, oldHostId); + } else if (event == Event.AgentReportStopped) { + releaseVmCapacity(vm, false, true, oldHostId); + } + } else if (oldState == State.Running) { + if (event == Event.AgentReportStopped) { + releaseVmCapacity(vm, false, true, oldHostId); + } + } else if (oldState == State.Migrating) { + if (event == Event.AgentReportStopped) { + /*Release capacity from original host*/ + releaseVmCapacity(vm, false, false, vm.getLastHostId()); + releaseVmCapacity(vm, false, true, oldHostId); + } else if (event == Event.MigrationFailedOnSource) { + /*Release from dest host*/ + releaseVmCapacity(vm, false, false, oldHostId); + } else if (event == Event.OperationSucceeded) { + releaseVmCapacity(vm, false, false, vm.getLastHostId()); + } + } else if (oldState == State.Stopping) { + if (event == Event.AgentReportStopped || event == Event.OperationSucceeded) { + releaseVmCapacity(vm, false, true, oldHostId); + } + } else if (oldState == State.Stopped) { + if (event == Event.DestroyRequested) { + releaseVmCapacity(vm, true, false, vm.getLastHostId()); + } + } + + return true; + } + } diff --git a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java index a92bf45821d..74a60393e35 100644 --- a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java +++ b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java @@ -92,7 +92,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { } @Override - public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vm, boolean status) { + public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vm, boolean status, Long oldHostId) { if (!_isEnabled || !status || (vm.getType() != VirtualMachine.Type.User && vm.getType() != VirtualMachine.Type.DomainRouter)) { return false; } diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index 813fd7c1476..c3dbcc5a230 100644 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -1329,7 +1329,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG } @Override - public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vm, boolean status) { + public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vm, boolean status, Long oldHostId) { if (!status) { return false; } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 735a280532f..236bfad8c34 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -138,7 +138,7 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @Local(value=VirtualMachineManager.class) -public class VirtualMachineManagerImpl implements VirtualMachineManager, StateListener, Listener { +public class VirtualMachineManagerImpl implements VirtualMachineManager, Listener { private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class); String _name; @@ -445,7 +445,6 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, StateLi _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vm-Operations-Cleanup")); _nodeId = _clusterMgr.getId(); - _stateMachine.registerListener(this); _agentMgr.registerForHostEvents(this, true, true, true); return true; } @@ -906,6 +905,12 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, StateLi @Override public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId) { + State oldState = vm.getState(); + if (oldState == State.Starting ) { + if (e == Event.OperationSucceeded) { + vm.setLastHostId(hostId); + } + } return _stateMachine.transitTo(vm, e, hostId, _vmDao); } @@ -1157,67 +1162,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, StateLi return rebootedVm; } - @Override - public boolean preStateTransitionEvent(State oldState, - Event event, State newState, VirtualMachine vm, boolean transitionStatus, Long id) { - s_logger.debug("VM state transitted from :" + oldState + " to " + newState + " with event: " + event + - "vm's original host id: " + vm.getHostId() + " new host id: " + id); - if (!transitionStatus) { - return false; - } - - if (oldState == State.Starting) { - if (event == Event.OperationSucceeded) { - if (vm.getLastHostId() != null && vm.getLastHostId() != id) { - /*need to release the reserved capacity on lasthost*/ - _capacityMgr.releaseVmCapacity(vm, true, false, vm.getLastHostId()); - } - vm.setLastHostId(id); - } else if (event == Event.OperationFailed) { - _capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); - } else if (event == Event.OperationRetry) { - _capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); - } else if (event == Event.AgentReportStopped) { - _capacityMgr.releaseVmCapacity(vm, false, true, vm.getHostId()); - } - } else if (oldState == State.Running) { - if (event == Event.AgentReportStopped) { - _capacityMgr.releaseVmCapacity(vm, false, true, vm.getHostId()); - } - } else if (oldState == State.Migrating) { - if (event == Event.AgentReportStopped) { - /*Release capacity from original host*/ - _capacityMgr.releaseVmCapacity(vm, false, true, vm.getHostId()); - } else if (event == Event.MigrationFailedOnSource) { - /*release capacity from dest host*/ - _capacityMgr.releaseVmCapacity(vm, false, false, id); - id = vm.getHostId(); - } else if (event == Event.MigrationFailedOnDest) { - /*release capacify from original host*/ - _capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); - } else if (event == Event.OperationSucceeded) { - _capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); - /*set lasthost id to migration destination host id*/ - vm.setLastHostId(id); - } - } else if (oldState == State.Stopping) { - if (event == Event.AgentReportStopped || event == Event.OperationSucceeded) { - _capacityMgr.releaseVmCapacity(vm, false, true, vm.getHostId()); - } - } else if (oldState == State.Stopped) { - if (event == Event.DestroyRequested) { - _capacityMgr.releaseVmCapacity(vm, true, false, vm.getLastHostId()); - vm.setLastHostId(null); - } - } - return transitionStatus; - } - - @Override - public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status) { - return true; - } - + @Override public VMInstanceVO findById(VirtualMachine.Type type, long vmId) { VirtualMachineGuru guru = _vmGurus.get(type); diff --git a/utils/src/com/cloud/utils/fsm/StateListener.java b/utils/src/com/cloud/utils/fsm/StateListener.java index 2e5654489bc..78bbee0d0d4 100644 --- a/utils/src/com/cloud/utils/fsm/StateListener.java +++ b/utils/src/com/cloud/utils/fsm/StateListener.java @@ -24,5 +24,5 @@ public interface StateListener { * @param status the state transition is allowed or not * @return */ - public boolean postStateTransitionEvent(S oldState, E event, S newState, V vo, boolean status); + public boolean postStateTransitionEvent(S oldState, E event, S newState, V vo, boolean status, Long id); } \ No newline at end of file diff --git a/utils/src/com/cloud/utils/fsm/StateMachine2.java b/utils/src/com/cloud/utils/fsm/StateMachine2.java index 1a4cd7f7c99..5312049ffe8 100644 --- a/utils/src/com/cloud/utils/fsm/StateMachine2.java +++ b/utils/src/com/cloud/utils/fsm/StateMachine2.java @@ -108,10 +108,11 @@ public class StateMachine2> { listener.preStateTransitionEvent(currentState, e, nextState, vo, transitionStatus, id); } + Long oldHostId = vo.getHostId(); transitionStatus = dao.updateState(currentState, e, nextState, vo, id); for (StateListener listener : _listeners) { - listener.postStateTransitionEvent(currentState, e, nextState, vo, transitionStatus); + listener.postStateTransitionEvent(currentState, e, nextState, vo, transitionStatus, oldHostId); } return transitionStatus; diff --git a/utils/src/com/cloud/utils/fsm/StateObject.java b/utils/src/com/cloud/utils/fsm/StateObject.java index 8aa2fc9ac57..22571f1eb08 100644 --- a/utils/src/com/cloud/utils/fsm/StateObject.java +++ b/utils/src/com/cloud/utils/fsm/StateObject.java @@ -5,4 +5,5 @@ public interface StateObject { * @return finite state. */ S getState(); + Long getHostId(); }