This commit is contained in:
edison 2010-12-02 18:56:10 -08:00
parent e99cc740e6
commit 2e3ef1408c
16 changed files with 211 additions and 162 deletions

View File

@ -72,7 +72,7 @@
<adapter name="KVM Agent" class="com.cloud.hypervisor.kvm.discoverer.KvmServerDiscoverer"/>
</adapters>
<adapters key="com.cloud.deploy.DeploymentPlanner">
<adapter name="Simple" class="com.cloud.deploy.SimplePlanner"/>
<adapter name="First Fit" class="com.cloud.deploy.FirstFitPlanner"/>
</adapters>
<adapters key="com.cloud.network.element.NetworkElement">
<adapter name="DomainRouter" class="com.cloud.network.element.DomainRouterElement"/>

View File

@ -2112,10 +2112,12 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, ResourceS
List<CapacityVO> capacities = _capacityDao.search(capacitySC, null);
// remove old entries, we'll recalculate them anyway
if ((capacities != null) && !capacities.isEmpty()) {
for (CapacityVO capacity : capacities) {
_capacityDao.remove(capacity.getId());
}
if (startup instanceof StartupStorageCommand) {
if ((capacities != null) && !capacities.isEmpty()) {
for (CapacityVO capacity : capacities) {
_capacityDao.remove(capacity.getId());
}
}
}
if (startup instanceof StartupStorageCommand) {
@ -2130,14 +2132,57 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, ResourceS
_capacityDao.persist(capacity);
}
} else if (startup instanceof StartupRoutingCommand) {
CapacityVO capacity = new CapacityVO(server.getId(), server.getDataCenterId(), server.getPodId(), 0L,
server.getTotalMemory(), CapacityVO.CAPACITY_TYPE_MEMORY);
_capacityDao.persist(capacity);
capacity = new CapacityVO(server.getId(), server.getDataCenterId(), server.getPodId(), 0L, (long)(server.getCpus().longValue()
* server.getSpeed().longValue()*_cpuOverProvisioningFactor), CapacityVO.CAPACITY_TYPE_CPU);
_capacityDao.persist(capacity);
SearchCriteria<CapacityVO> capacityCPU = _capacityDao.createSearchCriteria();
capacityCPU.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, server.getId());
capacityCPU.addAnd("dataCenterId", SearchCriteria.Op.EQ, server.getDataCenterId());
capacityCPU.addAnd("podId", SearchCriteria.Op.EQ, server.getPodId());
capacityCPU.addAnd("capacityType", SearchCriteria.Op.EQ, CapacityVO.CAPACITY_TYPE_CPU);
List<CapacityVO> capacityVOCpus = _capacityDao.search(capacitySC, null);
if (capacityVOCpus != null && !capacityVOCpus.isEmpty()) {
CapacityVO CapacityVOCpu = capacityVOCpus.get(0);
long newTotalCpu = (long)(server.getCpus().longValue() * server.getSpeed().longValue()*_cpuOverProvisioningFactor);
if (CapacityVOCpu.getTotalCapacity() < newTotalCpu) {
CapacityVOCpu.setTotalCapacity(newTotalCpu);
} else if (CapacityVOCpu.getUsedCapacity() + CapacityVOCpu.getReservedCapacity() > newTotalCpu && CapacityVOCpu.getUsedCapacity() < newTotalCpu) {
CapacityVOCpu.setReservedCapacity(0);
CapacityVOCpu.setTotalCapacity(newTotalCpu);
} else {
s_logger.debug("What? new cpu is :" + newTotalCpu + ", old one is " + CapacityVOCpu.getUsedCapacity() + "," + CapacityVOCpu.getReservedCapacity() + "," +
CapacityVOCpu.getTotalCapacity());
}
_capacityDao.update(CapacityVOCpu.getId(), CapacityVOCpu);
} else {
CapacityVO capacity = new CapacityVO(server.getId(), server.getDataCenterId(), server.getPodId(), 0L, (long)(server.getCpus().longValue()
* server.getSpeed().longValue()*_cpuOverProvisioningFactor), CapacityVO.CAPACITY_TYPE_CPU);
_capacityDao.persist(capacity);
}
SearchCriteria<CapacityVO> capacityMem = _capacityDao.createSearchCriteria();
capacityMem.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, server.getId());
capacityMem.addAnd("dataCenterId", SearchCriteria.Op.EQ, server.getDataCenterId());
capacityMem.addAnd("podId", SearchCriteria.Op.EQ, server.getPodId());
capacityMem.addAnd("capacityType", SearchCriteria.Op.EQ, CapacityVO.CAPACITY_TYPE_MEMORY);
List<CapacityVO> capacityVOMems = _capacityDao.search(capacitySC, null);
if (capacityVOMems != null && !capacityVOMems.isEmpty()) {
CapacityVO CapacityVOMem = capacityVOMems.get(0);
long newTotalMem = server.getTotalMemory();
if (CapacityVOMem.getTotalCapacity() < newTotalMem) {
CapacityVOMem.setTotalCapacity(newTotalMem);
} else if (CapacityVOMem.getUsedCapacity() + CapacityVOMem.getReservedCapacity() > newTotalMem && CapacityVOMem.getUsedCapacity() < newTotalMem) {
CapacityVOMem.setReservedCapacity(0);
CapacityVOMem.setTotalCapacity(newTotalMem);
} else {
s_logger.debug("What? new cpu is :" + newTotalMem + ", old one is " + CapacityVOMem.getUsedCapacity() + "," + CapacityVOMem.getReservedCapacity() + "," +
CapacityVOMem.getTotalCapacity());
}
_capacityDao.update(CapacityVOMem.getId(), CapacityVOMem);
} else {
CapacityVO capacity = new CapacityVO(server.getId(), server.getDataCenterId(), server.getPodId(), 0L,
server.getTotalMemory(), CapacityVO.CAPACITY_TYPE_MEMORY);
_capacityDao.persist(capacity);
}
}
}

View File

@ -20,9 +20,11 @@ package com.cloud.capacity.dao;
import com.cloud.capacity.CapacityVO;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.VMInstanceVO;
public interface CapacityDao extends GenericDao<CapacityVO, Long> {
void clearNonStorageCapacities();
void clearStorageCapacities();
CapacityVO findByHostIdType(Long hostId, short capacityType);
CapacityVO findByHostIdType(Long hostId, short capacityType);
}

View File

@ -25,10 +25,13 @@ import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.capacity.CapacityVO;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.VMInstanceVO;
@Local(value = { CapacityDao.class })
public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements CapacityDao {
@ -37,10 +40,10 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
private static final String ADD_ALLOCATED_SQL = "UPDATE `cloud`.`op_host_capacity` SET used_capacity = used_capacity + ? WHERE host_id = ? AND capacity_type = ?";
private static final String SUBTRACT_ALLOCATED_SQL = "UPDATE `cloud`.`op_host_capacity` SET used_capacity = used_capacity - ? WHERE host_id = ? AND capacity_type = ?";
private static final String CLEAR_STORAGE_CAPACITIES = "DELETE FROM `cloud`.`op_host_capacity` WHERE capacity_type=2 OR capacity_type=3 OR capacity_type=6"; //clear storage and secondary_storage capacities
private static final String CLEAR_NON_STORAGE_CAPACITIES = "DELETE FROM `cloud`.`op_host_capacity` WHERE capacity_type<>2 AND capacity_type<>3 AND capacity_type<>6"; //clear non-storage and non-secondary_storage capacities
private static final String CLEAR_NON_STORAGE_CAPACITIES = "DELETE FROM `cloud`.`op_host_capacity` WHERE capacity_type<>2 AND capacity_type<>3 AND capacity_type<>6 AND capacity_type<>0 AND capacity_type<>1"; //clear non-storage and non-secondary_storage capacities
private SearchBuilder<CapacityVO> _hostIdTypeSearch;
public void CapacityDaoImple() {
public CapacityDaoImpl() {
_hostIdTypeSearch = createSearchBuilder();
_hostIdTypeSearch.and("hostId", _hostIdTypeSearch.entity().getHostOrPoolId(), SearchCriteria.Op.EQ);
_hostIdTypeSearch.and("type", _hostIdTypeSearch.entity().getCapacityType(), SearchCriteria.Op.EQ);

View File

@ -2357,7 +2357,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx
String multicastRateStr = _configDao.getValue("multicast.throttling.rate");
_networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr));
_multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr));
_serviceOffering = new ServiceOfferingVO("System Offering For Console Proxy", 1, _proxyRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtualized,
_serviceOffering = new ServiceOfferingVO("System Offering For Console Proxy", 1, _proxyRamSize, 500, 0, 0, false, null, NetworkOffering.GuestIpType.Virtualized,
useLocalStorage, true, null, true);
_serviceOffering.setUniqueName("Cloud.com-ConsoleProxy");
_serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering);

View File

@ -3,6 +3,8 @@ package com.cloud.deploy;
import java.util.Collections;
import java.util.List;
import javax.ejb.Local;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.dc.ClusterVO;
@ -20,10 +22,11 @@ import com.cloud.host.dao.HostDao;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value=DeploymentPlanner.class)
public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
@Inject private HostDao _hostDao;
@Inject private CapacityDao _capacityDao;
@ -95,15 +98,24 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
return null;
}
private boolean deployToHost(Long hostId, Integer cpu, long ram, boolean fromLastHost) {
@Override
public boolean check(VirtualMachineProfile vm, DeploymentPlan plan,
DeployDestination dest, ExcludeList exclude) {
// TODO Auto-generated method stub
return false;
}
@DB
protected boolean deployToHost(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();
txn.start();
try {
txn.start();
capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true);
capacityMem = _capacityDao.lockRow(capacityMem.getId(), true);
@ -119,21 +131,23 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
/*alloc from reserved*/
if (reservedCpu >= cpu && reservedMem >= ram) {
capacityCpu.setReservedCapacity(reservedCpu - cpu);
capacityMem.setReservedCapacity(reservedMem - ram);
capacityMem.setReservedCapacity(reservedMem - ram);
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(totalMem + ram);
capacityMem.setUsedCapacity(usedMem + ram);
success = true;
}
}
if (success) {
_capacityDao.update(capacityCpu.getId(), capacityCpu);
_capacityDao.update(capacityMem.getId(), capacityMem);
_capacityDao.update(capacityMem.getId(), capacityMem);
}
txn.commit();
@ -143,11 +157,5 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
return false;
}
}
@Override
public boolean check(VirtualMachineProfile vm, DeploymentPlan plan,
DeployDestination dest, ExcludeList exclude) {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -359,9 +359,8 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
if (work.getStep() == Step.Investigating) {
if (vm.getHostId() == null || vm.getHostId() != work.getHostId()) {
s_logger.info("VM " + vm.toString() + " is now no longer on host " + work.getHostId());
if (vm.getState() == State.Starting && vm.getUpdated() == work.getUpdateTime()) {
vm.setHostId(null);
_itMgr.stateTransitTo(vm, Event.AgentReportStopped);
if (vm.getState() == State.Starting && vm.getUpdated() == work.getUpdateTime()) {
_itMgr.stateTransitTo(vm, Event.AgentReportStopped, null);
}
return null;
}
@ -521,7 +520,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
s_logger.debug("Both states are " + agentState.toString() + " for " + serverName);
}
assert (agentState == State.Stopped || agentState == State.Running) : "If the states we send up is changed, this must be changed.";
_itMgr.stateTransitTo(vm, agentState == State.Stopped ? VirtualMachine.Event.AgentReportStopped : VirtualMachine.Event.AgentReportRunning);
_itMgr.stateTransitTo(vm, agentState == State.Stopped ? VirtualMachine.Event.AgentReportStopped : VirtualMachine.Event.AgentReportRunning, vm.getHostId());
if (agentState == State.Stopped) {
s_logger.debug("State matches but the agent said stopped so let's send a cleanup anyways.");
return info.mgr.cleanup(vm, agentName);
@ -551,9 +550,8 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
} else if (serverState == State.Starting) {
s_logger.debug("Ignoring VM in starting mode: " + vm.getHostName());
} else {
s_logger.debug("Sending cleanup to a stopped vm: " + agentName);
vm.setHostId(null);
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportStopped);
s_logger.debug("Sending cleanup to a stopped vm: " + agentName);
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportStopped, null);
command = info.mgr.cleanup(vm, agentName);
}
} else if (agentState == State.Running) {
@ -577,7 +575,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
vm = info.mgr.get(vm.getId());
command = info.mgr.cleanup(vm, agentName);
} else {
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning);
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, vm.getHostId());
}
} /*else if (agentState == State.Unknown) {
if (serverState == State.Running) {
@ -749,7 +747,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
if (work.getStep() == Step.Migrating) {
vm = mgr.get(vmId); // let's see if anything has changed.
boolean migrated = false;
if (vm == null || vm.getRemoved() != null || vm.getHostId() == null || !_itMgr.stateTransitTo(vm, Event.MigrationRequested)) {
if (vm == null || vm.getRemoved() != null || vm.getHostId() == null || !_itMgr.stateTransitTo(vm, Event.MigrationRequested, vm.getHostId())) {
s_logger.info("Migration cancelled because state has changed: " + vm.toString());
} else {
try {
@ -779,7 +777,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
HostPodVO podVO = _podDao.findById(vm.getPodId());
_alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getHostName() + " from host " + fromHost.getName() + " in zone " + dcVO.getName() + " and pod " + podVO.getName(), "Migrate Command failed. Please check logs.");
_itMgr.stateTransitTo(vm, Event.OperationFailed);
_itMgr.stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
_agentMgr.maintenanceFailed(vm.getHostId());
Command cleanup = mgr.cleanup(vm, null);
@ -809,8 +807,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
} catch (final OperationTimedoutException e) {
s_logger.warn("Operation timed outfor " + vm.toString());
}
vm.setHostId(toHost.getId());
_itMgr.stateTransitTo(vm, Event.OperationFailed);
_itMgr.stateTransitTo(vm, Event.OperationFailed, toHost.getId());
return (System.currentTimeMillis() >> 10) + _migrateRetryInterval;
}

View File

@ -1517,7 +1517,7 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute
String multicastRateStr = _configDao.getValue("multicast.throttling.rate");
_networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr));
_multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr));
_offering = new ServiceOfferingVO("System Offering For Software Router", 1, _routerRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtualized, useLocalStorage, true, null, true);
_offering = new ServiceOfferingVO("System Offering For Software Router", 1, _routerRamSize, 500, 0, 0, false, null, NetworkOffering.GuestIpType.Virtualized, useLocalStorage, true, null, true);
_offering.setUniqueName("Cloud.Com-SoftwareRouter");
_offering = _serviceOfferingDao.persistSystemServiceOffering(_offering);
_template = _templateDao.findRoutingTemplate();

View File

@ -1466,7 +1466,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V
String multicastRateStr = _configDao.getValue("multicast.throttling.rate");
_networkRate = ((networkRateStr == null) ? 200 : Integer.parseInt(networkRateStr));
_multicastRate = ((multicastRateStr == null) ? 10 : Integer.parseInt(multicastRateStr));
_serviceOffering = new ServiceOfferingVO("System Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 0, 0, 0, false, null, NetworkOffering.GuestIpType.Virtualized, useLocalStorage, true, null, true);
_serviceOffering = new ServiceOfferingVO("System Offering For Secondary Storage VM", 1, _secStorageVmRamSize, 500, 0, 0, false, null, NetworkOffering.GuestIpType.Virtualized, useLocalStorage, true, null, true);
_serviceOffering.setUniqueName("Cloud.com-SecondaryStorage");
_serviceOffering = _offeringDao.persistSystemServiceOffering(_serviceOffering);
_template = _templateDao.findConsoleProxyTemplate();

View File

@ -174,7 +174,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
_storageMgr.allocateRawVolume(VolumeType.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner);
}
stateTransitTo(vm, Event.OperationSucceeded);
stateTransitTo(vm, Event.OperationSucceeded, null);
txn.commit();
if (s_logger.isDebugEnabled()) {
s_logger.debug("Allocation completed for VM: " + vm);
@ -238,7 +238,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Destroying vm " + vm);
}
if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested)) {
if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) {
s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm.toString());
return false;
}
@ -326,7 +326,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
vm.setReservationId(work.getId());
if (!stateTransitTo(vm, Event.StartRequested)) {
if (!stateTransitTo(vm, Event.StartRequested, null)) {
throw new ConcurrentOperationException("Unable to start vm " + vm + " due to concurrent operations");
}
@ -334,7 +334,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
int retry = _retry;
while (retry-- != 0) { // It's != so that it can match -1.
if (retry < (_retry -1)) {
stateTransitTo(vm, Event.OperationRetry);
stateTransitTo(vm, Event.OperationRetry, null);
}
VirtualMachineProfileImpl<T> vmProfile = new VirtualMachineProfileImpl<T>(vm, template, offering, null, params);
@ -353,13 +353,12 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
}
vm.setDataCenterId(dest.getDataCenter().getId());
vm.setPodId(dest.getPod().getId());
vm.setHostId(dest.getHost().getId());
vm.setPodId(dest.getPod().getId());
try {
_storageMgr.prepare(vmProfile, dest);
} catch (ConcurrentOperationException e) {
stateTransitTo(vm, Event.OperationFailed);
stateTransitTo(vm, Event.OperationFailed, null);
throw e;
} catch (StorageUnavailableException e) {
s_logger.warn("Unable to contact storage.", e);
@ -379,7 +378,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
try {
Answer[] answers = _agentMgr.send(dest.getHost().getId(), cmds);
if (answers[0].getResult() && vmGuru.finalizeStart(cmds, vmProfile, dest, context)) {
if (!stateTransitTo(vm, Event.OperationSucceeded)) {
if (!stateTransitTo(vm, Event.OperationSucceeded, dest.getHost().getId())) {
throw new CloudRuntimeException("Unable to transition to a new state.");
}
return vm;
@ -394,7 +393,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
}
}
stateTransitTo(vm, Event.OperationFailed);
stateTransitTo(vm, Event.OperationFailed, null);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Creation complete for VM " + vm);
@ -418,7 +417,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
return true;
}
if (!stateTransitTo(vm, Event.StopRequested)) {
if (!stateTransitTo(vm, Event.StopRequested, vm.getHostId())) {
throw new ConcurrentOperationException("VM is being operated on by someone else.");
}
@ -447,7 +446,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
}
} finally {
if (!stopped) {
stateTransitTo(vm, Event.OperationFailed);
stateTransitTo(vm, Event.OperationFailed, vm.getHostId());
}
}
@ -482,8 +481,8 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
}
vm.setReservationId(null);
vm.setHostId(null);
stateTransitTo(vm, Event.OperationSucceeded);
stateTransitTo(vm, Event.OperationSucceeded, null);
if (cleanup) {
ItWorkVO work = new ItWorkVO(reservationId, _nodeId, Type.Cleanup);
@ -541,7 +540,7 @@ public class MauriceMoss implements VmManager, ClusterManagerListener {
}
@Override
public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e) {
return _stateMachine.transitTO(vm, e);
public boolean stateTransitTo(VMInstanceVO vm, VirtualMachine.Event e, Long id) {
return _stateMachine.transitTO(vm, e, id);
}
}

View File

@ -22,9 +22,8 @@ public class VMStateListener implements StateListener<State, VirtualMachine.Even
}
@Override
@DB
public boolean processStateTransitionEvent(State oldState,
Event event, State newState, VMInstanceVO vm, boolean transitionStatus) {
Event event, State newState, VMInstanceVO vm, boolean transitionStatus, Long id) {
if (oldState == State.Starting) {
if (event == Event.OperationRetry || event == Event.OperationFailed) {
releaseResource(vm, false, false);
@ -34,89 +33,95 @@ public class VMStateListener implements StateListener<State, VirtualMachine.Even
if (!transitionStatus) {
return true;
}
Transaction txn = Transaction.open(Transaction.CLOUD_DB);
try {
txn.start();
if (oldState == State.Starting) {
if (event == Event.OperationSucceeded) {
vm.setLastHostId(id);
_vmDao.update(vm.getId(), vm);
}
} else if (oldState == State.Running) {
if (event == Event.AgentReportStopped) {
releaseResource(vm, false, true);
}
} else if (oldState == State.Migrating) {
if (event == Event.AgentReportStopped) {
releaseResource(vm, false, true);
}
} else if (oldState == State.Stopping) {
if (event == Event.AgentReportStopped || event == Event.OperationSucceeded) {
releaseResource(vm, false, true);
}
} else if (oldState == State.Stopped) {
if (event == Event.DestroyRequested) {
releaseResource(vm, true, false);
vm.setLastHostId(null);
_vmDao.update(vm.getId(), vm);
}
}
transitionStatus = _vmDao.updateState(oldState, event, newState, vm, id);
if (transitionStatus) {
txn.commit();
} else {
txn.rollback();
}
} catch (Exception e) {
txn.rollback();
} finally {
txn.close();
}
if (oldState == State.Starting) {
if (event == Event.OperationSucceeded) {
vm.setLastHostId(vm.getHostId());
_vmDao.update(vm.getId(), vm);
return transitionStatus;
}
private void releaseResource(VMInstanceVO vm, boolean moveFromReserved, boolean moveToReservered) {
ServiceOfferingVO svo = _offeringDao.findById(vm.getServiceOfferingId());
CapacityVO capacityCpu = _capacityDao.findByHostIdType(vm.getHostId(), CapacityVO.CAPACITY_TYPE_CPU);
CapacityVO capacityMemory = _capacityDao.findByHostIdType(vm.getHostId(), CapacityVO.CAPACITY_TYPE_MEMORY);
int vmCPU = svo.getCpu() * svo.getSpeed();
int vmMem = svo.getRamSize();
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 (oldState == State.Running) {
if (event == Event.AgentReportStopped) {
releaseResource(vm, false, true);
} else {
if (reservedCpu >= vmCPU) {
capacityCpu.setReservedCapacity(reservedCpu - vmCPU);
}
} else if (oldState == State.Migrating) {
if (event == Event.AgentReportStopped) {
releaseResource(vm, false, true);
}
} else if (oldState == State.Stopping) {
if (event == Event.AgentReportStopped || event == Event.OperationSucceeded) {
releaseResource(vm, false, true);
}
} else if (oldState == State.Stopped) {
if (event == Event.DestroyRequested) {
releaseResource(vm, true, false);
vm.setLastHostId(null);
_vmDao.update(vm.getId(), vm);
if (reservedMem >= vmMem) {
capacityMemory.setReservedCapacity(reservedMem - vmMem);
}
}
return true;
}
@DB
private void releaseResource(VMInstanceVO vm, boolean moveFromReserved, boolean moveToReservered) {
CapacityVO capacityCpu = _capacityDao.findByHostIdType(vm.getHostId(), CapacityVO.CAPACITY_TYPE_CPU);
CapacityVO capacityMemory = _capacityDao.findByHostIdType(vm.getHostId(), CapacityVO.CAPACITY_TYPE_MEMORY);
ServiceOfferingVO offeringVO = _offeringDao.findById(vm.getServiceOfferingId());
int cpu = offeringVO.getCpu();
int speed = offeringVO.getSpeed();
int vmCPU = cpu * speed;
int vmMem = offeringVO.getRamSize();
Transaction txn = Transaction.currentTxn();
txn.start();
try {
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();
_capacityDao.update(capacityCpu.getId(), capacityCpu);
_capacityDao.update(capacityMemory.getId(), capacityMemory);
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);
}
}
_capacityDao.update(capacityCpu.getId(), capacityCpu);
_capacityDao.update(capacityMemory.getId(), capacityMemory);
txn.commit();
} catch (Exception e) {
txn.rollback();
}
}
}

View File

@ -77,6 +77,6 @@ public interface VmManager extends Manager {
<T extends VMInstanceVO> void registerGuru(VirtualMachine.Type type, VirtualMachineGuru<T> guru);
boolean stateTransitTo(VMInstanceVO vm, Event e);
boolean stateTransitTo(VMInstanceVO vm, Event e, Long id);
}

View File

@ -295,7 +295,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
@Override
public boolean updateState(State oldState, Event event,
State newState, VMInstanceVO vm) {
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());
@ -312,7 +312,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
vm.incrUpdated();
UpdateBuilder ub = getUpdateBuilder(vm);
ub.set(vm, "state", newState);
ub.set(vm, "hostId", vm.getHostId());
ub.set(vm, "hostId", hostId);
ub.set(vm, _updateTimeAttr, new Date());
int result = update(vm, sc);

View File

@ -1,5 +1,7 @@
package com.cloud.utils.fsm;
public interface StateDao <S,E,V> {
boolean updateState(S currentState, E event, S nextState, V vo);
boolean updateState(S currentState, E event, S nextState, V vo, Long id);
}

View File

@ -1,5 +1,5 @@
package com.cloud.utils.fsm;
public interface StateListener <S,E,V> {
public boolean processStateTransitionEvent(S oldState, E event, S newState, V vo, boolean status);
public boolean processStateTransitionEvent(S oldState, E event, S newState, V vo, boolean status, Long id);
}

View File

@ -97,35 +97,23 @@ public class StateMachine2<S, E, V extends StateObject<S>> {
return entry.prevStates.get(e);
}
@DB
public boolean transitTO(V vo, E e) {
public boolean transitTO(V vo, E e, Long id) {
S currentState = vo.getState();
S nextState = getNextState(currentState, e);
boolean transitionStatus = true;
if (nextState == null) {
transitionStatus = false;
}
Transaction txn = Transaction.currentTxn();
txn.start();
try {
transitionStatus = _instanceDao.updateState(currentState, e, nextState, vo);
for (StateListener<S,E, V> listener : _listeners) {
listener.processStateTransitionEvent(currentState, e, nextState, vo, transitionStatus);
}
txn.commit();
} catch (Exception ex) {
txn.rollback();
for (StateListener<S,E, V> listener : _listeners) {
transitionStatus = listener.processStateTransitionEvent(currentState, e, nextState, vo, transitionStatus, id);
}
return transitionStatus;
}
public boolean registerListener(StateListener<S,E,V> listener) {
return _listeners.add(listener);
}