refactor vmstatelistener

This commit is contained in:
Edison Su 2011-01-26 11:01:20 -05:00
parent 5be450ff47
commit fc97034000
21 changed files with 534 additions and 713 deletions

View File

@ -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<State, Event> {
public interface VirtualMachine extends RunningOn, ControlledEntity, StateObject<VirtualMachine.State> {
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<State> getFromStates(VirtualMachine.Event e) {
return s_fsm.getFromStates(this, e);
}
@Override
public Set<Event> getPossibleEvents() {
return s_fsm.getPossibleEvents(this);
}
@Override
public StateMachine<State, Event> getStateMachine() {
public static StateMachine2<State, VirtualMachine.Event, VirtualMachine> getStateMachine() {
return s_fsm;
}
protected static final StateMachine<State, VirtualMachine.Event> s_fsm = new StateMachine<State, VirtualMachine.Event>();
protected static final StateMachine2<State, VirtualMachine.Event, VirtualMachine> s_fsm = new StateMachine2<State, VirtualMachine.Event, VirtualMachine>();
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?
*/

View File

@ -74,9 +74,6 @@
<adapters key="com.cloud.deploy.DeploymentPlanner">
<adapter name="First Fit" class="com.cloud.deploy.FirstFitPlanner"/>
</adapters>
<adapters key="com.cloud.utils.fsm.StateListener">
<adapter name="VMStateListener" class="com.cloud.stateListener.VMStateListener"/>
</adapters>
<adapters key="com.cloud.network.element.NetworkElement">
<adapter name="DomainRouter" class="com.cloud.network.element.VirtualRouterElement"/>
<adapter name="Dhcp" class="com.cloud.network.element.DhcpElement"/>

View File

@ -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<State, VirtualMachine.Event>, StateObject<State> {
public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, VirtualMachine.Event> {
@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)

View File

@ -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);
}

View File

@ -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<String, Object> 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<HostVO> sc = _hostDao.createSearchCriteria();
sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString());
List<HostVO> hosts = _hostDao.search(sc, null);
// prep the service offerings
List<ServiceOfferingVO> offerings = _offeringsDao.listAllIncludingRemoved();
Map<Long, ServiceOfferingVO> offeringsMap = new HashMap<Long, ServiceOfferingVO>();
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<VMInstanceVO> 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<VMInstanceVO> 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) {
}
}
}
}
}
}

View File

@ -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 <T> List<ComponentInfo<Adapter>> addAdapterChain(Class<T> interphace, List<Pair<String, Class<? extends T>>> adapters) {

View File

@ -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<HostVO> prioritizeHosts(VirtualMachineTemplate template, List<HostVO> hosts) {

View File

@ -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);

View File

@ -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<State, VirtualMachine.Event, VirtualMachine> {
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<String> {
@ -315,8 +301,8 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
return DigestUtils.md5Hex(ruleset);
}
protected void handleVmStarted(UserVm userVm) {
Set<Long> affectedVms = getAffectedVmsForVmStart(userVm);
protected void handleVmStarted(VMInstanceVO vm) {
Set<Long> affectedVms = getAffectedVmsForVmStart(vm);
scheduleRulesetUpdateToHosts(affectedVms, true, null);
}
@ -372,10 +358,10 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
}
}
protected Set<Long> getAffectedVmsForVmStart(UserVm userVm) {
protected Set<Long> getAffectedVmsForVmStart(VMInstanceVO vm) {
Set<Long> affectedVms = new HashSet<Long>();
affectedVms.add(userVm.getId());
List<SecurityGroupVMMapVO> groupsForVm = _securityGroupVMMapDao.listByInstanceId(userVm.getId());
affectedVms.add(vm.getId());
List<SecurityGroupVMMapVO> 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<IngressRuleVO> allowingRules = _ingressRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId());
@ -385,9 +371,9 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG
return affectedVms;
}
protected Set<Long> getAffectedVmsForVmStop(UserVm userVm) {
protected Set<Long> getAffectedVmsForVmStop(VMInstanceVO vm) {
Set<Long> affectedVms = new HashSet<Long>();
List<SecurityGroupVMMapVO> groupsForVm = _securityGroupVMMapDao.listByInstanceId(userVm.getId());
List<SecurityGroupVMMapVO> 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<IngressRuleVO> 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<Long> affectedVms = getAffectedVmsForVmStop(userVm);
protected void handleVmStopped(VMInstanceVO vm) {
Set<Long> 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<IngressRuleVO> 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;
}
}

View File

@ -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<State, VirtualMachine.Event, VMInstanceVO> {
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<State, VirtualMachine.Event, VMInstanceVO> 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<String, Object> 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<HostVO> sc = _hostDao.createSearchCriteria();
sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString());
List<HostVO> hosts = _hostDao.search(sc, null);
// prep the service offerings
List<ServiceOfferingVO> offerings = _offeringsDao.listAllIncludingRemoved();
Map<Long, ServiceOfferingVO> offeringsMap = new HashMap<Long, ServiceOfferingVO>();
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<VMInstanceVO> 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<VMInstanceVO> 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) {
}
}
}
}
}
}

View File

@ -2199,7 +2199,6 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
@Override
public boolean finalizeStart(VirtualMachineProfile<UserVmVO> 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<UserVmVO> profile, StopAnswer answer) {
UserVmVO vm = profile.getVirtualMachine();
_networkGroupMgr.handleVmStateTransition(vm, State.Stopped);
_ovsNetworkMgr.handleVmStateTransition(vm, State.Stopped);
_ovsTunnelMgr.CheckAndDestroyTunnel(vm);
}

View File

@ -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.

View File

@ -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<State, VirtualMachine.Event, VirtualMachine> {
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<DeploymentPlanner> _planners;
@Inject(adapter=StateListener.class)
protected Adapters<StateListener<State, VirtualMachine.Event, VMInstanceVO>> _stateListner;
Map<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>> _vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru<? extends VMInstanceVO>>();
Map<HypervisorType, HypervisorGuru> _hvGurus = new HashMap<HypervisorType, HypervisorGuru>();
protected StateMachine2<State, VirtualMachine.Event, VMInstanceVO> _stateMachine;
protected StateMachine2<State, VirtualMachine.Event, VirtualMachine> _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<State, VirtualMachine.Event, VMInstanceVO>();
_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;
}
}

View File

@ -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<DomainRouterVO, Long>, StateDao<State, VirtualMachine.Event, VMInstanceVO> {
public interface DomainRouterDao extends GenericDao<DomainRouterVO, Long>{
/**
* gets the DomainRouterVO by user id and data center
* @Param dcId data center Id.
@ -55,16 +51,6 @@ public interface DomainRouterDao extends GenericDao<DomainRouterVO, Long>, State
*/
public List<DomainRouterVO> 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.

View File

@ -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<DomainRouterVO, Long> 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<DomainRouterVO> 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<DomainRouterVO> listByDataCenter(long dcId) {
SearchCriteria<DomainRouterVO> sc = DcSearch.create();
@ -294,41 +239,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase<DomainRouterVO, Long> 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<DomainRouterVO> 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<DomainRouterVO> listByLastHostId(Long hostId) {
SearchCriteria<DomainRouterVO> sc = LastHostSearch.create();

View File

@ -31,7 +31,7 @@ import com.cloud.vm.VirtualMachine.State;
/*
* Data Access Object for vm_instance table
*/
public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<State, VirtualMachine.Event, VMInstanceVO> {
public interface VMInstanceDao extends GenericDao<VMInstanceVO, Long>, StateDao<State, VirtualMachine.Event, VirtualMachine> {
/**
* What are the vms running on this host?
* @param hostId host.

View File

@ -280,32 +280,33 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> 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<VMInstanceVO> 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;

View File

@ -52,6 +52,5 @@ public interface FiniteState<S, E> {
* @return array of events.
*/
Set<E> getPossibleEvents();
String getDescription();
}

View File

@ -18,10 +18,6 @@
package com.cloud.utils.fsm;
public interface FiniteStateObject<S, E> {
/**
* @return finite state.
*/
FiniteState<S, E> getState();
void setState(S state);
}

View File

@ -1,8 +1,28 @@
package com.cloud.utils.fsm;
import com.cloud.utils.component.Adapter;
public interface StateListener <S,E,V> extends Adapter{
public boolean processStateTransitionEvent(S oldState, E event, S newState, V vo, boolean status, Long id, StateDao<S,E,V> vmDao);
public interface StateListener <S,E,V> {
/**
* 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);
}

View File

@ -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<S, E, V extends StateObject<S>> {
}
for (StateListener<S,E, V> 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<S,E, V> listener : _listeners) {
listener.postStateTransitionEvent(currentState, e, nextState, vo, transitionStatus);
}
return transitionStatus;
}
public boolean registerListener(StateListener<S,E,V> listener) {
return _listeners.add(listener);
}
public boolean registerListeners(Adapters<StateListener<S,E,V>> listeners) {
for (StateListener<S,E,V> listener : listeners) {
_listeners.add(listener);
}
return true;
synchronized (_listeners) {
return _listeners.add(listener);
}
}
@Override