diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index 80bea781a02..06d0ea9b986 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -18,20 +18,19 @@ package com.cloud.vm; import java.util.Date; -import java.util.List; -import java.util.Set; import com.cloud.acl.ControlledEntity; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.utils.fsm.FiniteState; -import com.cloud.utils.fsm.StateMachine; +import com.cloud.utils.fsm.StateMachine2; +import com.cloud.utils.fsm.StateObject; + /** * VirtualMachine describes the properties held by a virtual machine * */ -public interface VirtualMachine extends RunningOn, ControlledEntity { - public enum State implements FiniteState { +public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject { + public enum State { Starting(true, "VM is being started. At this state, you should find host id filled which means it's being started on that host."), Running(false, "VM is running. host id has the host that it is running on."), Stopping(true, "VM is being stopped. host id has the host that it is being stopped on."), @@ -52,7 +51,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity { _description = description; } - @Override public String getDescription() { return _description; } @@ -61,68 +59,71 @@ public interface VirtualMachine extends RunningOn, ControlledEntity { return _transitional; } - @Override - public State getNextState(VirtualMachine.Event e) { - return s_fsm.getNextState(this, e); - } - - @Override - public List getFromStates(VirtualMachine.Event e) { - return s_fsm.getFromStates(this, e); - } - - @Override - public Set getPossibleEvents() { - return s_fsm.getPossibleEvents(this); - } - - @Override - public StateMachine getStateMachine() { + public static StateMachine2 getStateMachine() { return s_fsm; } - - protected static final StateMachine s_fsm = new StateMachine(); + protected static final StateMachine2 s_fsm = new StateMachine2(); 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.Stopped, VirtualMachine.Event.StartRequested, State.Starting); + s_fsm.addTransition(State.Stopped, 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.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.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.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.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); + 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.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.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); + 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); + s_fsm.addTransition(State.Error, VirtualMachine.Event.ExpungeOperation, State.Expunging); + } + + public static boolean isVmStarted(State oldState, Event e, State newState) { + if (oldState == State.Starting && newState == State.Running) { + return true; + } + return false; + } + + public static boolean isVmStopped(State oldState, Event e, State newState) { + if (oldState == State.Stopping && newState == State.Stopped) { + return true; + } + return false; + } + + public static boolean isVmMigrated(State oldState, Event e, State newState) { + if (oldState == State.Migrating && newState == State.Running && (e == Event.OperationSucceeded || e == Event.AgentReportRunning)) { + return true; + } + return false; } } @@ -182,7 +183,7 @@ public interface VirtualMachine extends RunningOn, ControlledEntity { /** * @return the state of the virtual machine */ - public State getState(); + //public State getState(); /** * @return template id. @@ -209,7 +210,9 @@ public interface VirtualMachine extends RunningOn, ControlledEntity { * @return id of the host it was assigned last time. */ public Long getLastHostId(); - + + public void setLastHostId(Long lastHostId); + /** * @return should HA be enabled for this machine? */ diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index f021a7fe50c..ced81d2dd8a 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -74,9 +74,6 @@ - - - diff --git a/core/src/com/cloud/vm/VMInstanceVO.java b/core/src/com/cloud/vm/VMInstanceVO.java index 23cd9ef9707..b45e944f484 100644 --- a/core/src/com/cloud/vm/VMInstanceVO.java +++ b/core/src/com/cloud/vm/VMInstanceVO.java @@ -39,14 +39,13 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.GenericDao; import com.cloud.utils.db.StateMachine; import com.cloud.utils.fsm.FiniteStateObject; -import com.cloud.utils.fsm.StateObject; import com.cloud.vm.VirtualMachine.State; @Entity @Table(name="vm_instance") @Inheritance(strategy=InheritanceType.JOINED) @DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING, length=32) -public class VMInstanceVO implements VirtualMachine, FiniteStateObject, StateObject { +public class VMInstanceVO implements VirtualMachine, FiniteStateObject { @Id @TableGenerator(name="vm_instance_sq", table="sequence", pkColumnName="name", valueColumnName="value", pkColumnValue="vm_instance_seq", allocationSize=1) @Column(name="id", updatable=false, nullable = false) diff --git a/server/src/com/cloud/capacity/CapacityManager.java b/server/src/com/cloud/capacity/CapacityManager.java index 4dcec032d68..bea487653fb 100644 --- a/server/src/com/cloud/capacity/CapacityManager.java +++ b/server/src/com/cloud/capacity/CapacityManager.java @@ -1,6 +1,7 @@ package com.cloud.capacity; import com.cloud.utils.component.Manager; +import com.cloud.vm.VirtualMachine; /** * Capacity Manager manages the different capacities @@ -8,5 +9,7 @@ import com.cloud.utils.component.Manager; * */ public interface CapacityManager extends Manager { + public boolean releaseVmCapacity(VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId); + boolean allocateVmCapacity(long hostId, Integer cpu, long ram, boolean fromLastHost); } diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 97cd56eef33..99de6ea878c 100644 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -17,30 +17,75 @@ */ package com.cloud.capacity; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.ejb.Local; import javax.naming.ConfigurationException; -import com.cloud.capacity.dao.CapacityDao; -import com.cloud.utils.component.Inject; +import org.apache.log4j.Logger; +import com.cloud.capacity.dao.CapacityDao; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.offering.ServiceOffering; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.utils.DateUtil; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.component.Inject; +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.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.VMInstanceDao; + +@Local(value=CapacityManager.class) public class CapacityManagerImpl implements CapacityManager { + private static final Logger s_logger = Logger.getLogger(CapacityManagerImpl.class); String _name; @Inject CapacityDao _capacityDao; + @Inject ConfigurationDao _configDao; + @Inject ServiceOfferingDao _offeringsDao; + @Inject HostDao _hostDao; + @Inject VMInstanceDao _vmDao; + private int _hostCapacityCheckerDelay; + private int _hostCapacityCheckerInterval; + private int _vmCapacityReleaseInterval; + private ScheduledExecutorService _executor; + private boolean _stopped; + @Override public boolean configure(String name, Map params) throws ConfigurationException { _name = name; + _hostCapacityCheckerDelay = NumbersUtil.parseInt(_configDao.getValue(Config.HostCapacityCheckerWait.key()), 3600); + _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")); return true; } @Override public boolean start() { + _executor.schedule(new HostCapacityCollector(), _hostCapacityCheckerDelay, TimeUnit.SECONDS); return true; } @Override public boolean stop() { + _executor.shutdownNow(); + _stopped = true; return true; } @@ -48,4 +93,241 @@ public class CapacityManagerImpl implements CapacityManager { public String getName() { return _name; } + + @DB + @Override + public boolean releaseVmCapacity(VirtualMachine vm, boolean moveFromReserved, boolean moveToReservered, Long hostId) { + ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); + CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); + CapacityVO capacityMemory = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); + + if (capacityCpu == null || capacityMemory == null || svo == null) { + return false; + } + + Transaction txn = Transaction.currentTxn(); + try { + txn.start(); + + int vmCPU = svo.getCpu() * svo.getSpeed(); + long vmMem = svo.getRamSize() * 1024L * 1024L; + + capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true); + capacityMemory = _capacityDao.lockRow(capacityMemory.getId(), true); + + long usedCpu = capacityCpu.getUsedCapacity(); + long usedMem = capacityMemory.getUsedCapacity(); + long reservedCpu = capacityCpu.getReservedCapacity(); + long reservedMem = capacityMemory.getReservedCapacity(); + long totalCpu = capacityCpu.getTotalCapacity(); + long totalMem = capacityMemory.getTotalCapacity(); + + if (!moveFromReserved) { + /*move resource from used*/ + if (usedCpu >= vmCPU) { + capacityCpu.setUsedCapacity(usedCpu - vmCPU); + } + if (usedMem >= vmMem) { + capacityMemory.setUsedCapacity(usedMem - vmMem); + } + + if (moveToReservered) { + if (reservedCpu + vmCPU <= totalCpu) { + capacityCpu.setReservedCapacity(reservedCpu + vmCPU); + } + if (reservedMem + vmMem <= totalMem) { + capacityMemory.setReservedCapacity(reservedMem + vmMem); + } + } + } else { + if (reservedCpu >= vmCPU) { + capacityCpu.setReservedCapacity(reservedCpu - vmCPU); + } + if (reservedMem >= vmMem) { + capacityMemory.setReservedCapacity(reservedMem - vmMem); + } + } + + s_logger.debug("release cpu from host: " + hostId + ", old used: " + usedCpu + ",reserved: " + reservedCpu + ", total: " + totalCpu + + "; new used: " + capacityCpu.getUsedCapacity() + ",reserved:" + capacityCpu.getReservedCapacity() + ",total: " + capacityCpu.getTotalCapacity() + + "; movedfromreserved: " + moveFromReserved + ",moveToReservered" + moveToReservered); + + s_logger.debug("release mem from host: " + hostId + ", old used: " + usedMem + ",reserved: " + reservedMem + ", total: " + totalMem + + "; new used: " + capacityMemory.getUsedCapacity() + ",reserved:" + capacityMemory.getReservedCapacity() + ",total: " + capacityMemory.getTotalCapacity() + + "; movedfromreserved: " + moveFromReserved + ",moveToReservered" + moveToReservered); + + _capacityDao.update(capacityCpu.getId(), capacityCpu); + _capacityDao.update(capacityMemory.getId(), capacityMemory); + txn.commit(); + return true; + } catch (Exception e) { + s_logger.debug("Failed to transit vm's state, due to " + e.getMessage()); + txn.rollback(); + return false; + } + } + + @DB + @Override + public boolean allocateVmCapacity(long hostId, Integer cpu, long ram, boolean fromLastHost) { + CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); + CapacityVO capacityMem = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); + + Transaction txn = Transaction.currentTxn(); + + try { + txn.start(); + capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true); + capacityMem = _capacityDao.lockRow(capacityMem.getId(), true); + + long usedCpu = capacityCpu.getUsedCapacity(); + long usedMem = capacityMem.getUsedCapacity(); + long reservedCpu = capacityCpu.getReservedCapacity(); + long reservedMem = capacityMem.getReservedCapacity(); + long totalCpu = capacityCpu.getTotalCapacity(); + long totalMem = capacityMem.getTotalCapacity(); + + boolean success = false; + if (fromLastHost) { + /*alloc from reserved*/ + if (reservedCpu >= cpu && reservedMem >= ram) { + capacityCpu.setReservedCapacity(reservedCpu - cpu); + capacityMem.setReservedCapacity(reservedMem - ram); + if ((usedCpu + reservedCpu + cpu <= totalCpu) && (reservedMem + usedMem + ram <= totalMem)) { + capacityCpu.setUsedCapacity(usedCpu + cpu); + capacityMem.setUsedCapacity(usedMem + ram); + } + success = true; + } + } else { + /*alloc from free resource*/ + if ((reservedCpu + usedCpu + cpu <= totalCpu) && (reservedMem + usedMem + ram <= totalMem)) { + capacityCpu.setUsedCapacity(usedCpu + cpu); + capacityMem.setUsedCapacity(usedMem + ram); + success = true; + } + } + + if (success) { + s_logger.debug("alloc cpu from host: " + hostId + ", old used: " + usedCpu + ", old reserved: " + + reservedCpu + ", old total: " + totalCpu + + "; new used:" + capacityCpu.getUsedCapacity() + ", reserved:" + capacityCpu.getReservedCapacity() + ", total: " + capacityCpu.getTotalCapacity() + + "; requested cpu:" + cpu + ",alloc_from_last:" + fromLastHost); + + s_logger.debug("alloc mem from host: " + hostId + ", old used: " + usedMem + ", old reserved: " + + reservedMem + ", old total: " + totalMem + "; new used: " + capacityMem.getUsedCapacity() + ", reserved: " + + capacityMem.getReservedCapacity() + ", total: " + capacityMem.getTotalCapacity() + "; requested mem: " + ram + ",alloc_from_last:" + fromLastHost); + + _capacityDao.update(capacityCpu.getId(), capacityCpu); + _capacityDao.update(capacityMem.getId(), capacityMem); + } else { + if (fromLastHost) { + s_logger.debug("Failed to alloc resource from host: " + hostId + " reservedCpu: " + reservedCpu + ", requested cpu: " + cpu + + ", reservedMem: " + reservedMem + ", requested mem: " + ram); + } else { + s_logger.debug("Failed to alloc resource from host: " + hostId + " reservedCpu: " + reservedCpu + ", used cpu: " + usedCpu + ", requested cpu: " + cpu + + ", total cpu: " + totalCpu + + ", reservedMem: " + reservedMem + ", used Mem: " + usedMem + ", requested mem: " + ram + ", total Mem:" + totalMem); + } + } + + txn.commit(); + return success; + } catch (Exception e) { + txn.rollback(); + return false; + } + } + + public class HostCapacityCollector implements Runnable { + + @Override + public void run() { + while (!_stopped) { + try { + Thread.sleep(_hostCapacityCheckerInterval * 1000); + } catch (InterruptedException e1) { + + } + // get all hosts.. + SearchCriteria sc = _hostDao.createSearchCriteria(); + sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); + List hosts = _hostDao.search(sc, null); + + // prep the service offerings + List offerings = _offeringsDao.listAllIncludingRemoved(); + Map offeringsMap = new HashMap(); + for (ServiceOfferingVO offering : offerings) { + offeringsMap.put(offering.getId(), offering); + } + + for (HostVO host : hosts) { + if (host.getType() != Host.Type.Routing) { + continue; + } + + long usedCpu = 0; + long usedMemory = 0; + long reservedMemory = 0; + long reservedCpu = 0; + + List vms = _vmDao.listUpByHostId(host.getId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found " + vms.size() + " VMs on host " + host.getId()); + } + + for (VMInstanceVO vm : vms) { + ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); + usedMemory += so.getRamSize() * 1024L * 1024L; + usedCpu += so.getCpu() * so.getSpeed(); + } + + List vmsByLastHostId = _vmDao.listByLastHostId(host.getId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found " + vmsByLastHostId.size() + " VM, not running on host " + host.getId()); + } + for (VMInstanceVO vm : vmsByLastHostId) { + long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - vm.getUpdateTime().getTime())/1000; + if (secondsSinceLastUpdate < _vmCapacityReleaseInterval) { + ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); + reservedMemory += so.getRamSize() * 1024L * 1024L; + reservedCpu += so.getCpu() * so.getSpeed(); + } + } + + CapacityVO cpuCap = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_CPU); + CapacityVO memCap = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_MEMORY); + + if (cpuCap.getUsedCapacity() == usedCpu && cpuCap.getReservedCapacity() == reservedCpu) { + s_logger.debug("Cool, no need to calibrate cpu capacity, host:" + host.getId() + " usedCpu: " + cpuCap.getUsedCapacity() + " reservedCpu: " + cpuCap.getReservedCapacity()); + } else if (cpuCap.getReservedCapacity() != reservedCpu) { + s_logger.debug("Calibrate reserved cpu for host: " + host.getId() + " old reservedCpu:" + cpuCap.getReservedCapacity() + " new reservedCpu:" + reservedCpu); + cpuCap.setReservedCapacity(reservedCpu); + } else if (cpuCap.getUsedCapacity() != usedCpu) { + s_logger.debug("Calibrate used cpu for host: " + host.getId() + " old usedCpu:" + cpuCap.getUsedCapacity() + " new usedCpu:" + usedCpu); + cpuCap.setUsedCapacity(usedCpu); + } + + if (memCap.getUsedCapacity() == usedMemory && memCap.getReservedCapacity() == reservedMemory) { + s_logger.debug("Cool, no need to calibrate memory capacity, host:" + host.getId() + " usedMem: " + memCap.getUsedCapacity() + " reservedMem: " + memCap.getReservedCapacity()); + } else if (memCap.getReservedCapacity() != reservedMemory) { + s_logger.debug("Calibrate reserved memory for host: " + host.getId() + " old reservedMem:" + memCap.getReservedCapacity() + " new reservedMem:" + reservedMemory); + memCap.setReservedCapacity(reservedMemory); + } else if (memCap.getUsedCapacity() != usedMemory) { + /*Didn't calibrate for used memory, because VMs can be in state(starting/migrating) that I don't know on which host they are allocated*/ + s_logger.debug("Calibrate used memory for host: " + host.getId() + " old usedMem: " + memCap.getUsedCapacity() + " new usedMem: " + usedMemory); + memCap.setUsedCapacity(usedMemory); + } + + try { + _capacityDao.update(cpuCap.getId(), cpuCap); + _capacityDao.update(memCap.getId(), memCap); + } catch (Exception e) { + + } + } + + } + } + } } diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index c373dbdaa87..3d034379996 100644 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -33,6 +33,7 @@ import com.cloud.async.SyncQueueManagerImpl; import com.cloud.async.dao.AsyncJobDaoImpl; import com.cloud.async.dao.SyncQueueDaoImpl; import com.cloud.async.dao.SyncQueueItemDaoImpl; +import com.cloud.capacity.CapacityManagerImpl; import com.cloud.capacity.dao.CapacityDaoImpl; import com.cloud.certificate.dao.CertificateDaoImpl; import com.cloud.cluster.DummyClusterManagerImpl; @@ -313,6 +314,7 @@ public class DefaultComponentLibrary implements ComponentLibrary { addManager("RemoteAccessVpnManager", RemoteAccessVpnManagerImpl.class); addManager("OvsNetworkManager", OvsNetworkManagerImpl.class); addManager("OvsTunnelManager", OvsTunnelManagerImpl.class); + addManager("Capacity Manager", CapacityManagerImpl.class); } protected List> addAdapterChain(Class interphace, List>> adapters) { diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java index 3f8570febb3..770b6fad6b2 100644 --- a/server/src/com/cloud/deploy/FirstFitPlanner.java +++ b/server/src/com/cloud/deploy/FirstFitPlanner.java @@ -7,6 +7,7 @@ import javax.ejb.Local; import org.apache.log4j.Logger; +import com.cloud.capacity.CapacityManager; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; import com.cloud.dc.ClusterVO; @@ -47,6 +48,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { @Inject DetailsDao _hostDetailsDao = null; @Inject GuestOSDao _guestOSDao = null; @Inject GuestOSCategoryDao _guestOSCategoryDao = null; + @Inject CapacityManager _capacityMgr; @Override public DeployDestination plan(VirtualMachineProfile vmProfile, @@ -162,73 +164,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { return false; } - CapacityVO capacityCpu = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_CPU); - CapacityVO capacityMem = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_MEMORY); - - Transaction txn = Transaction.currentTxn(); - - try { - txn.start(); - capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true); - capacityMem = _capacityDao.lockRow(capacityMem.getId(), true); - - long usedCpu = capacityCpu.getUsedCapacity(); - long usedMem = capacityMem.getUsedCapacity(); - long reservedCpu = capacityCpu.getReservedCapacity(); - long reservedMem = capacityMem.getReservedCapacity(); - long totalCpu = capacityCpu.getTotalCapacity(); - long totalMem = capacityMem.getTotalCapacity(); - - boolean success = false; - if (fromLastHost) { - /*alloc from reserved*/ - if (reservedCpu >= cpu && reservedMem >= ram) { - capacityCpu.setReservedCapacity(reservedCpu - cpu); - capacityMem.setReservedCapacity(reservedMem - ram); - if ((usedCpu + reservedCpu + cpu <= totalCpu) && (reservedMem + usedMem + ram <= totalMem)) { - capacityCpu.setUsedCapacity(usedCpu + cpu); - capacityMem.setUsedCapacity(usedMem + ram); - } - success = true; - } - } else { - /*alloc from free resource*/ - if ((reservedCpu + usedCpu + cpu <= totalCpu) && (reservedMem + usedMem + ram <= totalMem)) { - capacityCpu.setUsedCapacity(usedCpu + cpu); - capacityMem.setUsedCapacity(usedMem + ram); - success = true; - } - } - - if (success) { - s_logger.debug("alloc cpu from host: " + host.getId() + ", old used: " + usedCpu + ", old reserved: " + - reservedCpu + ", old total: " + totalCpu + - "; new used:" + capacityCpu.getUsedCapacity() + ", reserved:" + capacityCpu.getReservedCapacity() + ", total: " + capacityCpu.getTotalCapacity() + - "; requested cpu:" + cpu + ",alloc_from_last:" + fromLastHost); - - s_logger.debug("alloc mem from host: " + host.getId() + ", old used: " + usedMem + ", old reserved: " + - reservedMem + ", old total: " + totalMem + "; new used: " + capacityMem.getUsedCapacity() + ", reserved: " + - capacityMem.getReservedCapacity() + ", total: " + capacityMem.getTotalCapacity() + "; requested mem: " + ram + ",alloc_from_last:" + fromLastHost); - - _capacityDao.update(capacityCpu.getId(), capacityCpu); - _capacityDao.update(capacityMem.getId(), capacityMem); - } else { - if (fromLastHost) { - s_logger.debug("Failed to alloc resource from host: " + host.getId() + " reservedCpu: " + reservedCpu + ", requested cpu: " + cpu + - ", reservedMem: " + reservedMem + ", requested mem: " + ram); - } else { - s_logger.debug("Failed to alloc resource from host: " + host.getId() + " reservedCpu: " + reservedCpu + ", used cpu: " + usedCpu + ", requested cpu: " + cpu + - ", total cpu: " + totalCpu + - ", reservedMem: " + reservedMem + ", used Mem: " + usedMem + ", requested mem: " + ram + ", total Mem:" + totalMem); - } - } - - txn.commit(); - return success; - } catch (Exception e) { - txn.rollback(); - return false; - } + return _capacityMgr.allocateVmCapacity(host.getId(), cpu, ram, fromLastHost); } protected List prioritizeHosts(VirtualMachineTemplate template, List hosts) { diff --git a/server/src/com/cloud/network/security/SecurityGroupManager.java b/server/src/com/cloud/network/security/SecurityGroupManager.java index 8fa2eb19d58..d171f4e9fe8 100644 --- a/server/src/com/cloud/network/security/SecurityGroupManager.java +++ b/server/src/com/cloud/network/security/SecurityGroupManager.java @@ -20,9 +20,8 @@ package com.cloud.network.security; import java.util.HashMap; import java.util.List; -import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; -import com.cloud.vm.VirtualMachine.State; + /** * Ensures that network firewall rules stay updated as VMs go up and down @@ -32,8 +31,6 @@ public interface SecurityGroupManager { public static final String DEFAULT_GROUP_NAME = "default"; public static final String DEFAULT_GROUP_DESCRIPTION = "Default Security Group"; - - public void handleVmStateTransition(UserVm userVm, State vmState); public SecurityGroupVO createSecurityGroup(String name, String description, Long domainId, Long accountId, String accountName); diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index 5e0e5dc8e74..184bff3cdbd 100644 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -40,6 +40,7 @@ import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; +import com.cloud.agent.api.NetworkRulesSystemVmCommand; import com.cloud.agent.api.SecurityIngressRulesCmd; import com.cloud.agent.api.SecurityIngressRulesCmd.IpPortAndProto; import com.cloud.agent.manager.Commands; @@ -55,6 +56,7 @@ import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceInUseException; import com.cloud.network.security.SecurityGroupWorkVO.Step; @@ -82,13 +84,18 @@ import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.fsm.StateListener; import com.cloud.utils.net.NetUtils; import com.cloud.vm.UserVmVO; +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.VirtualMachineManager; import com.cloud.vm.dao.UserVmDao; @Local(value={SecurityGroupManager.class, SecurityGroupService.class}) -public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityGroupService, Manager { +public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityGroupService, Manager, StateListener { public static final Logger s_logger = Logger.getLogger(SecurityGroupManagerImpl.class); @Inject SecurityGroupDao _securityGroupDao; @@ -102,6 +109,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG @Inject VmRulesetLogDao _rulesetLogDao; @Inject DomainDao _domainDao; @Inject AgentManager _agentMgr; + @Inject VirtualMachineManager _itMgr; ScheduledExecutorService _executorPool; ScheduledExecutorService _cleanupExecutor; @@ -242,29 +250,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG } - @Override - public void handleVmStateTransition(UserVm userVm, State vmState) { - if (!_enabled) { - return; - } - switch (vmState) { - case Destroyed: - case Error: - case Migrating: - case Expunging: - case Starting: - case Unknown: - return; - case Running: - handleVmStarted(userVm); - break; - case Stopping: - case Stopped: - handleVmStopped(userVm); - break; - } - - } + public static class CidrComparator implements Comparator { @@ -315,8 +301,8 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return DigestUtils.md5Hex(ruleset); } - protected void handleVmStarted(UserVm userVm) { - Set affectedVms = getAffectedVmsForVmStart(userVm); + protected void handleVmStarted(VMInstanceVO vm) { + Set affectedVms = getAffectedVmsForVmStart(vm); scheduleRulesetUpdateToHosts(affectedVms, true, null); } @@ -372,10 +358,10 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG } } - protected Set getAffectedVmsForVmStart(UserVm userVm) { + protected Set getAffectedVmsForVmStart(VMInstanceVO vm) { Set affectedVms = new HashSet(); - affectedVms.add(userVm.getId()); - List groupsForVm = _securityGroupVMMapDao.listByInstanceId(userVm.getId()); + affectedVms.add(vm.getId()); + List groupsForVm = _securityGroupVMMapDao.listByInstanceId(vm.getId()); //For each group, find the ingress rules that allow the group for (SecurityGroupVMMapVO mapVO: groupsForVm) {//FIXME: use custom sql in the dao List allowingRules = _ingressRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId()); @@ -385,9 +371,9 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return affectedVms; } - protected Set getAffectedVmsForVmStop(UserVm userVm) { + protected Set getAffectedVmsForVmStop(VMInstanceVO vm) { Set affectedVms = new HashSet(); - List groupsForVm = _securityGroupVMMapDao.listByInstanceId(userVm.getId()); + List groupsForVm = _securityGroupVMMapDao.listByInstanceId(vm.getId()); //For each group, find the ingress rules that allow the group for (SecurityGroupVMMapVO mapVO: groupsForVm) {//FIXME: use custom sql in the dao List allowingRules = _ingressRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId()); @@ -426,11 +412,22 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG return new SecurityIngressRulesCmd(guestIp, guestMac, vmName, vmId, signature, seqnum, result.toArray(new IpPortAndProto[result.size()])); } - protected void handleVmStopped(UserVm userVm) { - Set affectedVms = getAffectedVmsForVmStop(userVm); + protected void handleVmStopped(VMInstanceVO vm) { + Set affectedVms = getAffectedVmsForVmStop(vm); scheduleRulesetUpdateToHosts(affectedVms, true, null); } + protected void handleVmMigrated(VMInstanceVO vm) { + NetworkRulesSystemVmCommand nrc = new NetworkRulesSystemVmCommand(vm.getInstanceName(), vm.getType()); + Commands cmds = new Commands(nrc); + try { + _agentMgr.send(vm.getHostId(), cmds); + } catch (AgentUnavailableException e) { + s_logger.debug(e.toString()); + } catch (OperationTimedoutException e) { + s_logger.debug(e.toString()); + } + } @Override @DB @SuppressWarnings("rawtypes") public List authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressCmd cmd) throws InvalidParameterValueException, PermissionDeniedException{ @@ -969,7 +966,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG _executorPool = Executors.newScheduledThreadPool(10, new NamedThreadFactory("NWGRP")); _cleanupExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("NWGRP-Cleanup")); - + VirtualMachine.State.getStateMachine().registerListener(this); return true; } @@ -1428,4 +1425,27 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG } } + + @Override + public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, boolean status, Long id) { + return true; + } + + @Override + public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vm, boolean status) { + if (!_enabled || !status || vm.getType() != VirtualMachine.Type.User) { + return false; + } + + if (VirtualMachine.State.isVmStarted(oldState, event, newState)) { + handleVmStarted((VMInstanceVO)vm); + } else if (VirtualMachine.State.isVmStopped(oldState, event, newState)) { + handleVmStopped((VMInstanceVO)vm); + } else if (VirtualMachine.State.isVmMigrated(oldState, event, newState)) { + handleVmMigrated((VMInstanceVO)vm); + } + + return true; + } + } diff --git a/server/src/com/cloud/stateListener/VMStateListener.java b/server/src/com/cloud/stateListener/VMStateListener.java deleted file mode 100644 index 762f4b4101e..00000000000 --- a/server/src/com/cloud/stateListener/VMStateListener.java +++ /dev/null @@ -1,341 +0,0 @@ -package com.cloud.stateListener; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - -import com.cloud.capacity.CapacityVO; -import com.cloud.capacity.dao.CapacityDao; -import com.cloud.configuration.Config; -import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.host.Host; -import com.cloud.host.HostVO; -import com.cloud.host.Status; -import com.cloud.host.dao.HostDao; -import com.cloud.offering.ServiceOffering; -import com.cloud.service.ServiceOfferingVO; -import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.utils.DateUtil; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.component.AdapterBase; -import com.cloud.utils.component.Inject; -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.StateDao; -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=StateListener.class) -public class VMStateListener extends AdapterBase implements StateListener { - private static final Logger s_logger = Logger.getLogger(VMStateListener.class); - @Inject CapacityDao _capacityDao = null; - @Inject ServiceOfferingDao _offeringsDao = null; - @Inject HostDao _hostDao = null; - @Inject VMInstanceDao _vmDao = null; - @Inject ConfigurationDao _configDao = null; - - ScheduledExecutorService _executor; - int _hostCapacityCheckerDelay; - int _hostCapacityCheckerInterval; - int _vmCapacityReleaseInterval; - boolean _stopped = false; - - @DB - @Override - public boolean processStateTransitionEvent(State oldState, - Event event, State newState, VMInstanceVO vm, boolean transitionStatus, Long id, StateDao vmDao) { - 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; - } - - Transaction txn = Transaction.currentTxn(); - try { - txn.start(); - - if (oldState == State.Starting) { - if (event == Event.OperationSucceeded) { - if (vm.getLastHostId() != null && vm.getLastHostId() != id) { - /*need to release the reserved capacity on lasthost*/ - releaseResource(vm, true, false, vm.getLastHostId()); - } - vm.setLastHostId(id); - } else if (event == Event.OperationFailed) { - releaseResource(vm, false, false, vm.getHostId()); - } else if (event == Event.OperationRetry) { - releaseResource(vm, false, false, vm.getHostId()); - } else if (event == Event.AgentReportStopped) { - releaseResource(vm, false, true, vm.getHostId()); - } - } else if (oldState == State.Running) { - if (event == Event.AgentReportStopped) { - releaseResource(vm, false, true, vm.getHostId()); - } - } else if (oldState == State.Migrating) { - if (event == Event.AgentReportStopped) { - /*Release capacity from original host*/ - releaseResource(vm, false, true, vm.getHostId()); - } else if (event == Event.MigrationFailedOnSource) { - /*release capacity from dest host*/ - releaseResource(vm, false, false, id); - id = vm.getHostId(); - } else if (event == Event.MigrationFailedOnDest) { - /*release capacify from original host*/ - releaseResource(vm, false, false, vm.getHostId()); - } else if (event == Event.OperationSucceeded) { - releaseResource(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) { - releaseResource(vm, false, true, vm.getHostId()); - } - } else if (oldState == State.Stopped) { - if (event == Event.DestroyRequested) { - releaseResource(vm, true, false, vm.getLastHostId()); - vm.setLastHostId(null); - } - } - - transitionStatus = vmDao.updateState(oldState, event, newState, vm, id); - if (transitionStatus) { - txn.commit(); - } else { - s_logger.debug("Failed to transit vm's state"); - txn.rollback(); - } - } catch (Exception e) { - s_logger.debug("Failed to transit vm's state, due to " + e.getMessage()); - txn.rollback(); - } - - return transitionStatus; - } - - private void releaseResource(VMInstanceVO vm, boolean moveFromReserved, boolean moveToReservered, Long hostId) { - ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); - CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU); - CapacityVO capacityMemory = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY); - - if (capacityCpu == null || capacityMemory == null || svo == null) { - return; - } - - int vmCPU = svo.getCpu() * svo.getSpeed(); - long vmMem = svo.getRamSize() * 1024L * 1024L; - - capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true); - capacityMemory = _capacityDao.lockRow(capacityMemory.getId(), true); - - long usedCpu = capacityCpu.getUsedCapacity(); - long usedMem = capacityMemory.getUsedCapacity(); - long reservedCpu = capacityCpu.getReservedCapacity(); - long reservedMem = capacityMemory.getReservedCapacity(); - long totalCpu = capacityCpu.getTotalCapacity(); - long totalMem = capacityMemory.getTotalCapacity(); - - if (!moveFromReserved) { - /*move resource from used*/ - if (usedCpu >= vmCPU) { - capacityCpu.setUsedCapacity(usedCpu - vmCPU); - } - if (usedMem >= vmMem) { - capacityMemory.setUsedCapacity(usedMem - vmMem); - } - - if (moveToReservered) { - if (reservedCpu + vmCPU <= totalCpu) { - capacityCpu.setReservedCapacity(reservedCpu + vmCPU); - } - if (reservedMem + vmMem <= totalMem) { - capacityMemory.setReservedCapacity(reservedMem + vmMem); - } - } - } else { - if (reservedCpu >= vmCPU) { - capacityCpu.setReservedCapacity(reservedCpu - vmCPU); - } - if (reservedMem >= vmMem) { - capacityMemory.setReservedCapacity(reservedMem - vmMem); - } - } - - s_logger.debug("release cpu from host: " + hostId + ", old used: " + usedCpu + ",reserved: " + reservedCpu + ", total: " + totalCpu + - "; new used: " + capacityCpu.getUsedCapacity() + ",reserved:" + capacityCpu.getReservedCapacity() + ",total: " + capacityCpu.getTotalCapacity() + - "; movedfromreserved: " + moveFromReserved + ",moveToReservered" + moveToReservered); - - s_logger.debug("release mem from host: " + hostId + ", old used: " + usedMem + ",reserved: " + reservedMem + ", total: " + totalMem + - "; new used: " + capacityMemory.getUsedCapacity() + ",reserved:" + capacityMemory.getReservedCapacity() + ",total: " + capacityMemory.getTotalCapacity() + - "; movedfromreserved: " + moveFromReserved + ",moveToReservered" + moveToReservered); - - _capacityDao.update(capacityCpu.getId(), capacityCpu); - _capacityDao.update(capacityMemory.getId(), capacityMemory); - - } - - /*Add capacity to destination host, for migration*/ - private void addResource(VMInstanceVO vm, Long destHostId) { - ServiceOfferingVO svo = _offeringsDao.findById(vm.getServiceOfferingId()); - CapacityVO capacityCpu = _capacityDao.findByHostIdType(destHostId, CapacityVO.CAPACITY_TYPE_CPU); - CapacityVO capacityMemory = _capacityDao.findByHostIdType(destHostId, CapacityVO.CAPACITY_TYPE_MEMORY); - int vmCPU = svo.getCpu() * svo.getSpeed(); - long vmMem = svo.getRamSize() * 1024L * 1024L; - - capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true); - capacityMemory = _capacityDao.lockRow(capacityMemory.getId(), true); - - long usedCpu = capacityCpu.getUsedCapacity(); - long usedMem = capacityMemory.getUsedCapacity(); - long reservedCpu = capacityCpu.getReservedCapacity(); - long reservedMem = capacityMemory.getReservedCapacity(); - long totalCpu = capacityCpu.getTotalCapacity(); - long totalMem = capacityMemory.getTotalCapacity(); - - if (usedCpu + reservedCpu + vmCPU <= totalCpu) { - capacityCpu.setUsedCapacity(usedCpu + vmCPU); - } else { - s_logger.debug("What's the heck? :u:" + usedCpu + ",r:" + reservedCpu + ",vm:" + vmCPU + " > " + totalCpu); - } - - if (usedMem + reservedMem + vmMem <= totalMem) { - capacityMemory.setUsedCapacity(usedMem + vmMem); - } else { - s_logger.debug("What's the heck? :u:" + usedMem + ",r:" + reservedMem + ",vm:" + vmMem + " > " + totalMem); - } - - _capacityDao.update(capacityCpu.getId(), capacityCpu); - _capacityDao.update(capacityMemory.getId(), capacityMemory); - - } - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - super.configure(name, params); - _hostCapacityCheckerDelay = NumbersUtil.parseInt(_configDao.getValue(Config.HostCapacityCheckerWait.key()), 3600); - _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")); - return true; - } - - @Override - public boolean start() { - _executor.schedule(new HostCapacityCollector(), _hostCapacityCheckerDelay, TimeUnit.SECONDS); - return true; - } - - @Override - public boolean stop() { - _executor.shutdownNow(); - _stopped = true; - return true; - } - - public class HostCapacityCollector implements Runnable { - - @Override - public void run() { - while (!_stopped) { - try { - Thread.sleep(_hostCapacityCheckerInterval * 1000); - } catch (InterruptedException e1) { - - } - // get all hosts.. - SearchCriteria sc = _hostDao.createSearchCriteria(); - sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); - List hosts = _hostDao.search(sc, null); - - // prep the service offerings - List offerings = _offeringsDao.listAllIncludingRemoved(); - Map offeringsMap = new HashMap(); - for (ServiceOfferingVO offering : offerings) { - offeringsMap.put(offering.getId(), offering); - } - - for (HostVO host : hosts) { - if (host.getType() != Host.Type.Routing) { - continue; - } - - long usedCpu = 0; - long usedMemory = 0; - long reservedMemory = 0; - long reservedCpu = 0; - - List vms = _vmDao.listUpByHostId(host.getId()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found " + vms.size() + " VMs on host " + host.getId()); - } - - for (VMInstanceVO vm : vms) { - ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); - usedMemory += so.getRamSize() * 1024L * 1024L; - usedCpu += so.getCpu() * so.getSpeed(); - } - - List vmsByLastHostId = _vmDao.listByLastHostId(host.getId()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found " + vmsByLastHostId.size() + " VM, not running on host " + host.getId()); - } - for (VMInstanceVO vm : vmsByLastHostId) { - long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - vm.getUpdateTime().getTime())/1000; - if (secondsSinceLastUpdate < _vmCapacityReleaseInterval) { - ServiceOffering so = offeringsMap.get(vm.getServiceOfferingId()); - reservedMemory += so.getRamSize() * 1024L * 1024L; - reservedCpu += so.getCpu() * so.getSpeed(); - } - } - - CapacityVO cpuCap = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_CPU); - CapacityVO memCap = _capacityDao.findByHostIdType(host.getId(), CapacityVO.CAPACITY_TYPE_MEMORY); - - if (cpuCap.getUsedCapacity() == usedCpu && cpuCap.getReservedCapacity() == reservedCpu) { - s_logger.debug("Cool, no need to calibrate cpu capacity, host:" + host.getId() + " usedCpu: " + cpuCap.getUsedCapacity() + " reservedCpu: " + cpuCap.getReservedCapacity()); - } else if (cpuCap.getReservedCapacity() != reservedCpu) { - s_logger.debug("Calibrate reserved cpu for host: " + host.getId() + " old reservedCpu:" + cpuCap.getReservedCapacity() + " new reservedCpu:" + reservedCpu); - cpuCap.setReservedCapacity(reservedCpu); - } else if (cpuCap.getUsedCapacity() != usedCpu) { - s_logger.debug("Calibrate used cpu for host: " + host.getId() + " old usedCpu:" + cpuCap.getUsedCapacity() + " new usedCpu:" + usedCpu); - cpuCap.setUsedCapacity(usedCpu); - } - - if (memCap.getUsedCapacity() == usedMemory && memCap.getReservedCapacity() == reservedMemory) { - s_logger.debug("Cool, no need to calibrate memory capacity, host:" + host.getId() + " usedMem: " + memCap.getUsedCapacity() + " reservedMem: " + memCap.getReservedCapacity()); - } else if (memCap.getReservedCapacity() != reservedMemory) { - s_logger.debug("Calibrate reserved memory for host: " + host.getId() + " old reservedMem:" + memCap.getReservedCapacity() + " new reservedMem:" + reservedMemory); - memCap.setReservedCapacity(reservedMemory); - } else if (memCap.getUsedCapacity() != usedMemory) { - /*Didn't calibrate for used memory, because VMs can be in state(starting/migrating) that I don't know on which host they are allocated*/ - s_logger.debug("Calibrate used memory for host: " + host.getId() + " old usedMem: " + memCap.getUsedCapacity() + " new usedMem: " + usedMemory); - memCap.setUsedCapacity(usedMemory); - } - - try { - _capacityDao.update(cpuCap.getId(), cpuCap); - _capacityDao.update(memCap.getId(), memCap); - } catch (Exception e) { - - } - } - - } - } - } -} diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 8dcb9aa6a89..35ae25d52ed 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2199,7 +2199,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Override public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { UserVmVO vm = profile.getVirtualMachine(); - _networkGroupMgr.handleVmStateTransition(vm, State.Running); _ovsNetworkMgr.handleVmStateTransition(vm, State.Running); UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VM_START, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getName(), vm.getServiceOfferingId(), vm.getTemplateId(), null); _usageEventDao.persist(usageEvent); @@ -2257,7 +2256,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Override public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { UserVmVO vm = profile.getVirtualMachine(); - _networkGroupMgr.handleVmStateTransition(vm, State.Stopped); _ovsNetworkMgr.handleVmStateTransition(vm, State.Stopped); _ovsTunnelMgr.CheckAndDestroyTunnel(vm); } diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index 43f9c1b8ce2..9f594f890b1 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -37,6 +37,9 @@ import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.Pair; import com.cloud.utils.component.Manager; +import com.cloud.utils.fsm.StateListener; +import com.cloud.vm.VirtualMachine.Event; +import com.cloud.vm.VirtualMachine.State; /** * Manages allocating resources to vms. diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 2f5d1ddd10d..e7fa5158f0f 100644 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -51,6 +51,7 @@ import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; import com.cloud.alert.AlertManager; +import com.cloud.capacity.CapacityManager; import com.cloud.cluster.ClusterManager; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; @@ -121,7 +122,7 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @Local(value=VirtualMachineManager.class) -public class VirtualMachineManagerImpl implements VirtualMachineManager { +public class VirtualMachineManagerImpl implements VirtualMachineManager, StateListener { private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class); String _name; @@ -150,16 +151,14 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager { @Inject protected VolumeDao _volsDao; @Inject protected ConsoleProxyManager _consoleProxyMgr; @Inject protected ConfigurationManager _configMgr; + @Inject protected CapacityManager _capacityMgr; @Inject(adapter=DeploymentPlanner.class) protected Adapters _planners; - @Inject(adapter=StateListener.class) - protected Adapters> _stateListner; - Map> _vmGurus = new HashMap>(); Map _hvGurus = new HashMap(); - protected StateMachine2 _stateMachine; + protected StateMachine2 _stateMachine; ScheduledExecutorService _executor = null; @@ -426,8 +425,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager { _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vm-Operations-Cleanup")); _nodeId = _clusterMgr.getId(); - setStateMachine(); - + _stateMachine.registerListener(this); return true; } @@ -437,6 +435,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager { } protected VirtualMachineManagerImpl() { + setStateMachine(); } @Override @@ -868,48 +867,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager { } private void setStateMachine() { - _stateMachine = new StateMachine2(); - - _stateMachine.addTransition(State.Stopped, VirtualMachine.Event.StartRequested, State.Starting); - _stateMachine.addTransition(State.Stopped, VirtualMachine.Event.DestroyRequested, State.Destroyed); - _stateMachine.addTransition(State.Stopped, VirtualMachine.Event.StopRequested, State.Stopped); - _stateMachine.addTransition(State.Stopped, VirtualMachine.Event.AgentReportStopped, State.Stopped); - _stateMachine.addTransition(State.Stopped, VirtualMachine.Event.OperationFailed, State.Error); - _stateMachine.addTransition(State.Stopped, VirtualMachine.Event.ExpungeOperation, State.Expunging); - _stateMachine.addTransition(State.Stopped, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); - _stateMachine.addTransition(State.Starting, VirtualMachine.Event.OperationRetry, State.Starting); - _stateMachine.addTransition(State.Starting, VirtualMachine.Event.OperationSucceeded, State.Running); - _stateMachine.addTransition(State.Starting, VirtualMachine.Event.OperationFailed, State.Stopped); - _stateMachine.addTransition(State.Starting, VirtualMachine.Event.AgentReportRunning, State.Running); - _stateMachine.addTransition(State.Starting, VirtualMachine.Event.AgentReportStopped, State.Stopped); - _stateMachine.addTransition(State.Starting, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); - _stateMachine.addTransition(State.Destroyed, VirtualMachine.Event.RecoveryRequested, State.Stopped); - _stateMachine.addTransition(State.Destroyed, VirtualMachine.Event.ExpungeOperation, State.Expunging); - _stateMachine.addTransition(State.Running, VirtualMachine.Event.MigrationRequested, State.Migrating); - _stateMachine.addTransition(State.Running, VirtualMachine.Event.AgentReportRunning, State.Running); - _stateMachine.addTransition(State.Running, VirtualMachine.Event.AgentReportStopped, State.Stopped); - _stateMachine.addTransition(State.Running, VirtualMachine.Event.StopRequested, State.Stopping); - _stateMachine.addTransition(State.Running, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); - _stateMachine.addTransition(State.Migrating, VirtualMachine.Event.MigrationRequested, State.Migrating); - _stateMachine.addTransition(State.Migrating, VirtualMachine.Event.OperationSucceeded, State.Running); - _stateMachine.addTransition(State.Migrating, VirtualMachine.Event.OperationFailed, State.Running); - _stateMachine.addTransition(State.Migrating, VirtualMachine.Event.MigrationFailedOnSource, State.Running); - _stateMachine.addTransition(State.Migrating, VirtualMachine.Event.MigrationFailedOnDest, State.Running); - _stateMachine.addTransition(State.Migrating, VirtualMachine.Event.AgentReportRunning, State.Running); - _stateMachine.addTransition(State.Migrating, VirtualMachine.Event.AgentReportStopped, State.Stopped); - _stateMachine.addTransition(State.Migrating, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); - _stateMachine.addTransition(State.Stopping, VirtualMachine.Event.OperationSucceeded, State.Stopped); - _stateMachine.addTransition(State.Stopping, VirtualMachine.Event.OperationFailed, State.Running); - _stateMachine.addTransition(State.Stopping, VirtualMachine.Event.AgentReportRunning, State.Running); - _stateMachine.addTransition(State.Stopping, VirtualMachine.Event.AgentReportStopped, State.Stopped); - _stateMachine.addTransition(State.Stopping, VirtualMachine.Event.StopRequested, State.Stopping); - _stateMachine.addTransition(State.Stopping, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); - _stateMachine.addTransition(State.Expunging, VirtualMachine.Event.OperationFailed, State.Expunging); - _stateMachine.addTransition(State.Expunging, VirtualMachine.Event.ExpungeOperation, State.Expunging); - _stateMachine.addTransition(State.Error, VirtualMachine.Event.DestroyRequested, State.Expunging); - _stateMachine.addTransition(State.Error, VirtualMachine.Event.ExpungeOperation, State.Expunging); - - _stateMachine.registerListeners(_stateListner); + _stateMachine = VirtualMachine.State.getStateMachine(); } protected boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long hostId, String reservationId) { @@ -1019,11 +977,6 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager { Commands cmds = new Commands(OnError.Revert); CheckVirtualMachineCommand cvm = new CheckVirtualMachineCommand(vm.getInstanceName()); cmds.addCommand(cvm); - - if (vm.getType() != VirtualMachine.Type.User) { - NetworkRulesSystemVmCommand nrc = new NetworkRulesSystemVmCommand(vm.getInstanceName(), vm.getType()); - cmds.addCommand(nrc); - } _agentMgr.send(dstHostId, cmds); CheckVirtualMachineAnswer answer = cmds.getAnswer(CheckVirtualMachineAnswer.class); @@ -1040,7 +993,6 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager { return null; } - // FIXME: _networkGroupMgr.handleVmStateTransition(vm, State.Running); stateTransitTo(vm, VirtualMachine.Event.OperationSucceeded, dstHostId); migrated = true; return vm; @@ -1176,5 +1128,65 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager { 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; + } } diff --git a/server/src/com/cloud/vm/dao/DomainRouterDao.java b/server/src/com/cloud/vm/dao/DomainRouterDao.java index 12d4dd59006..d1cadcc1efc 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDao.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDao.java @@ -21,17 +21,13 @@ import java.util.List; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.utils.db.GenericDao; -import com.cloud.utils.fsm.StateDao; import com.cloud.vm.DomainRouterVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachine.State; /** * * DomainRouterDao implements */ -public interface DomainRouterDao extends GenericDao, StateDao { +public interface DomainRouterDao extends GenericDao{ /** * gets the DomainRouterVO by user id and data center * @Param dcId data center Id. @@ -55,16 +51,6 @@ public interface DomainRouterDao extends GenericDao, State */ public List listBy(long userId); - /** - * Update the domainrouterVO only if the state is correct and the hostId is set. - * - * @param router router object - * @param event event that forces this update - * @param hostId host id to set to. - * @return true if update worked; false if not. - */ - public boolean updateIf(DomainRouterVO router, VirtualMachine.Event event, Long hostId); - /** * list virtual machine routers by host id. pass in null to get all * virtual machine routers. diff --git a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java index ac85af276a5..bfc0dff65f7 100755 --- a/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java +++ b/server/src/com/cloud/vm/dao/DomainRouterDaoImpl.java @@ -20,7 +20,6 @@ package com.cloud.vm.dao; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.Date; import java.util.List; import javax.ejb.Local; @@ -36,9 +35,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.db.UpdateBuilder; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DomainRouterVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachine.State; @Local(value = { DomainRouterDao.class }) @@ -148,57 +144,6 @@ public class DomainRouterDaoImpl extends GenericDaoBase im return result; } - @Override - public boolean updateIf(DomainRouterVO router, VirtualMachine.Event event, Long hostId) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("updateIf called on " + router.toString() + " event " + event.toString() + " host " + hostId); - } - State oldState = router.getState(); - State newState = oldState.getNextState(event); - long oldDate = router.getUpdated(); - - Long oldHostId = router.getHostId(); - - if (newState == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("There's no way to transition from old state: " + oldState.toString() + " event: " + event.toString()); - } - return false; - } - - SearchCriteria sc = StateChangeSearch.create(); - sc.setParameters("id", router.getId()); - sc.setParameters("states", oldState); - sc.setParameters("host", router.getHostId()); - sc.setParameters("update", router.getUpdated()); - - router.incrUpdated(); - UpdateBuilder ub = getUpdateBuilder(router); - if(newState == State.Running) { - // save current running host id - ub.set(router, "lastHostId", router.getHostId()); - } - - ub.set(router, "state", newState); - ub.set(router, "hostId", hostId); - ub.set(router, _updateTimeAttr, new Date()); - - int result = update(router, sc); - if (result == 0 && s_logger.isDebugEnabled()) { - DomainRouterVO vo = findById(router.getId()); - StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={Host=").append(vo.getHostId()).append("; State=").append(vo.getState().toString()).append("; updated=").append( - vo.getUpdated()); - str.append("} New Data: {Host=").append(router.getHostId()).append("; State=").append(router.getState().toString()).append("; updated=").append( - router.getUpdated()); - str.append("} Stale Data: {Host=").append(oldHostId).append("; State=").append(oldState.toString()).append("; updated=").append(oldDate) - .append("}"); - s_logger.debug(str.toString()); - } - - return result > 0; - } - @Override public List listByDataCenter(long dcId) { SearchCriteria sc = DcSearch.create(); @@ -294,41 +239,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase im return findOneIncludingRemovedBy(sc); } - @Override - public boolean updateState(State oldState, Event event, - State newState, VMInstanceVO vm, Long hostId) { - if (newState == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("There's no way to transition from old state: " + oldState.toString() + " event: " + event.toString()); - } - return false; - } - - DomainRouterVO routerVM = (DomainRouterVO)vm; - - SearchCriteria sc = StateChangeSearch.create(); - sc.setParameters("id", routerVM.getId()); - sc.setParameters("states", oldState); - sc.setParameters("host", routerVM.getHostId()); - sc.setParameters("update", routerVM.getUpdated()); - - vm.incrUpdated(); - UpdateBuilder ub = getUpdateBuilder(routerVM); - ub.set(routerVM, "state", newState); - ub.set(routerVM, "hostId", hostId); - ub.set(routerVM, _updateTimeAttr, new Date()); - - int result = update(routerVM, sc); - if (result == 0 && s_logger.isDebugEnabled()) { - DomainRouterVO vo = findById(routerVM.getId()); - StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={Host=").append(vo.getHostId()).append("; State=").append(vo.getState().toString()).append("; updated=").append(vo.getUpdated()); - str.append("} Stale Data: {Host=").append(routerVM.getHostId()).append("; State=").append(routerVM.getState().toString()).append("; updated=").append(routerVM.getUpdated()).append("}"); - s_logger.debug(str.toString()); - } - return result > 0; - } - + @Override public List listByLastHostId(Long hostId) { SearchCriteria sc = LastHostSearch.create(); diff --git a/server/src/com/cloud/vm/dao/VMInstanceDao.java b/server/src/com/cloud/vm/dao/VMInstanceDao.java index 31cf71c3edf..532394eb6f5 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDao.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDao.java @@ -31,7 +31,7 @@ import com.cloud.vm.VirtualMachine.State; /* * Data Access Object for vm_instance table */ -public interface VMInstanceDao extends GenericDao, StateDao { +public interface VMInstanceDao extends GenericDao, StateDao { /** * What are the vms running on this host? * @param hostId host. diff --git a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index 732278312ec..fda5ce998f8 100644 --- a/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/server/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -280,32 +280,33 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem @Override public boolean updateState(State oldState, Event event, - State newState, VMInstanceVO vm, Long hostId) { + State newState, VirtualMachine vm, Long hostId) { if (newState == null) { if (s_logger.isDebugEnabled()) { s_logger.debug("There's no way to transition from old state: " + oldState.toString() + " event: " + event.toString()); } return false; } + VMInstanceVO vmi = (VMInstanceVO)vm; SearchCriteria sc = StateChangeSearch.create(); - sc.setParameters("id", vm.getId()); + sc.setParameters("id", vmi.getId()); sc.setParameters("states", oldState); - sc.setParameters("host", vm.getHostId()); - sc.setParameters("update", vm.getUpdated()); + sc.setParameters("host", vmi.getHostId()); + sc.setParameters("update", vmi.getUpdated()); - vm.incrUpdated(); - UpdateBuilder ub = getUpdateBuilder(vm); - ub.set(vm, "state", newState); - ub.set(vm, "hostId", hostId); - ub.set(vm, _updateTimeAttr, new Date()); + vmi.incrUpdated(); + UpdateBuilder ub = getUpdateBuilder(vmi); + ub.set(vmi, "state", newState); + ub.set(vmi, "hostId", hostId); + ub.set(vmi, _updateTimeAttr, new Date()); - int result = update(vm, sc); + int result = update(vmi, sc); if (result == 0 && s_logger.isDebugEnabled()) { VMInstanceVO vo = findById(vm.getId()); StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); str.append(": DB Data={Host=").append(vo.getHostId()).append("; State=").append(vo.getState().toString()).append("; updated=").append(vo.getUpdated()); - str.append("} Stale Data: {Host=").append(vm.getHostId()).append("; State=").append(vm.getState().toString()).append("; updated=").append(vm.getUpdated()).append("}"); + str.append("} Stale Data: {Host=").append(vm.getHostId()).append("; State=").append(vm.getState().toString()).append("; updated=").append(vmi.getUpdated()).append("}"); s_logger.debug(str.toString()); } return result > 0; diff --git a/utils/src/com/cloud/utils/fsm/FiniteState.java b/utils/src/com/cloud/utils/fsm/FiniteState.java index ca0d1f668ca..eaab620d8b1 100644 --- a/utils/src/com/cloud/utils/fsm/FiniteState.java +++ b/utils/src/com/cloud/utils/fsm/FiniteState.java @@ -52,6 +52,5 @@ public interface FiniteState { * @return array of events. */ Set getPossibleEvents(); - String getDescription(); } diff --git a/utils/src/com/cloud/utils/fsm/FiniteStateObject.java b/utils/src/com/cloud/utils/fsm/FiniteStateObject.java index 277af6fb597..08a76e26aa7 100644 --- a/utils/src/com/cloud/utils/fsm/FiniteStateObject.java +++ b/utils/src/com/cloud/utils/fsm/FiniteStateObject.java @@ -18,10 +18,6 @@ package com.cloud.utils.fsm; public interface FiniteStateObject { - /** - * @return finite state. - */ - FiniteState getState(); - + void setState(S state); } diff --git a/utils/src/com/cloud/utils/fsm/StateListener.java b/utils/src/com/cloud/utils/fsm/StateListener.java index d271037b696..2e5654489bc 100644 --- a/utils/src/com/cloud/utils/fsm/StateListener.java +++ b/utils/src/com/cloud/utils/fsm/StateListener.java @@ -1,8 +1,28 @@ package com.cloud.utils.fsm; -import com.cloud.utils.component.Adapter; - - -public interface StateListener extends Adapter{ - public boolean processStateTransitionEvent(S oldState, E event, S newState, V vo, boolean status, Long id, StateDao vmDao); +public interface StateListener { + /** + * Event is triggered before state machine transition finished. + * If you want to get the state of vm before state machine changed, you need to listen on this event + * @param oldState VM's old state + * @param event that triggered this VM state change + * @param newState VM's new state + * @param vo the VM instance + * @param status the state transition is allowed or not + * @param id host id + * @param vmDao VM dao + * @return + */ + public boolean preStateTransitionEvent(S oldState, E event, S newState, V vo, boolean status, Long id); + + /** + * Event is triggered after state machine transition finished + * @param oldState VM's old state + * @param event that triggered this VM state change + * @param newState VM's new state + * @param vo the VM instance + * @param status the state transition is allowed or not + * @return + */ + public boolean postStateTransitionEvent(S oldState, E event, S newState, V vo, boolean status); } \ 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 85467756596..1a4cd7f7c99 100644 --- a/utils/src/com/cloud/utils/fsm/StateMachine2.java +++ b/utils/src/com/cloud/utils/fsm/StateMachine2.java @@ -24,10 +24,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import com.cloud.utils.component.Adapters; - - - /** * StateMachine is a partial implementation of a finite state machine. * Specifically, it implements the Moore machine. @@ -109,21 +105,22 @@ public class StateMachine2> { } for (StateListener listener : _listeners) { - transitionStatus = listener.processStateTransitionEvent(currentState, e, nextState, vo, transitionStatus, id, dao); + listener.preStateTransitionEvent(currentState, e, nextState, vo, transitionStatus, id); } + + transitionStatus = dao.updateState(currentState, e, nextState, vo, id); + + for (StateListener listener : _listeners) { + listener.postStateTransitionEvent(currentState, e, nextState, vo, transitionStatus); + } return transitionStatus; } public boolean registerListener(StateListener listener) { - return _listeners.add(listener); - } - - public boolean registerListeners(Adapters> listeners) { - for (StateListener listener : listeners) { - _listeners.add(listener); - } - return true; + synchronized (_listeners) { + return _listeners.add(listener); + } } @Override