Skip to content

Commit 41fdbfc

Browse files
committed
new allocator
1 parent ef9c9b8 commit 41fdbfc

16 files changed

Lines changed: 605 additions & 21 deletions

File tree

api/src/com/cloud/capacity/Capacity.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,7 @@ public interface Capacity {
3939
public long getTotalCapacity();
4040
public short getCapacityType();
4141

42+
long getReservedCapacity();
43+
4244

4345
}

core/src/com/cloud/capacity/CapacityVO.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ public class CapacityVO implements Capacity {
4444

4545
@Column(name="used_capacity")
4646
private long usedCapacity;
47-
47+
48+
@Column(name="reserved_capacity")
49+
private long reservedCapacity;
50+
4851
@Column(name="total_capacity")
4952
private long totalCapacity;
5053

@@ -96,6 +99,13 @@ public long getUsedCapacity() {
9699
}
97100
public void setUsedCapacity(long usedCapacity) {
98101
this.usedCapacity = usedCapacity;
102+
}
103+
@Override
104+
public long getReservedCapacity() {
105+
return reservedCapacity;
106+
}
107+
public void setReservedCapacity(long reservedCapacity) {
108+
this.usedCapacity = reservedCapacity;
99109
}
100110
@Override
101111
public long getTotalCapacity() {

core/src/com/cloud/vm/VMInstanceVO.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@
3838
import com.cloud.utils.db.GenericDao;
3939
import com.cloud.utils.db.StateMachine;
4040
import com.cloud.utils.fsm.FiniteStateObject;
41+
import com.cloud.utils.fsm.StateObject;
4142

4243
@Entity
4344
@Table(name="vm_instance")
4445
@Inheritance(strategy=InheritanceType.JOINED)
4546
@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING, length=32)
46-
public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, VirtualMachine.Event> {
47+
public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, VirtualMachine.Event>, StateObject<State> {
4748
@Id
4849
@TableGenerator(name="vm_instance_sq", table="sequence", pkColumnName="name", valueColumnName="value", pkColumnValue="vm_instance_seq", allocationSize=1)
4950
@Column(name="id", updatable=false, nullable = false)

server/src/com/cloud/capacity/dao/CapacityDao.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@
2323

2424
public interface CapacityDao extends GenericDao<CapacityVO, Long> {
2525
void clearNonStorageCapacities();
26-
void clearStorageCapacities();
26+
void clearStorageCapacities();
27+
CapacityVO findByHostIdType(Long hostId, short capacityType);
2728
}

server/src/com/cloud/capacity/dao/CapacityDaoImpl.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
import com.cloud.capacity.CapacityVO;
2828
import com.cloud.utils.db.GenericDaoBase;
29+
import com.cloud.utils.db.SearchBuilder;
30+
import com.cloud.utils.db.SearchCriteria;
2931
import com.cloud.utils.db.Transaction;
3032

3133
@Local(value = { CapacityDao.class })
@@ -35,8 +37,16 @@ public class CapacityDaoImpl extends GenericDaoBase<CapacityVO, Long> implements
3537
private static final String ADD_ALLOCATED_SQL = "UPDATE `cloud`.`op_host_capacity` SET used_capacity = used_capacity + ? WHERE host_id = ? AND capacity_type = ?";
3638
private static final String SUBTRACT_ALLOCATED_SQL = "UPDATE `cloud`.`op_host_capacity` SET used_capacity = used_capacity - ? WHERE host_id = ? AND capacity_type = ?";
3739
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
38-
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
39-
40+
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
41+
private SearchBuilder<CapacityVO> _hostIdTypeSearch;
42+
43+
public void CapacityDaoImple() {
44+
_hostIdTypeSearch = createSearchBuilder();
45+
_hostIdTypeSearch.and("hostId", _hostIdTypeSearch.entity().getHostOrPoolId(), SearchCriteria.Op.EQ);
46+
_hostIdTypeSearch.and("type", _hostIdTypeSearch.entity().getCapacityType(), SearchCriteria.Op.EQ);
47+
_hostIdTypeSearch.done();
48+
}
49+
4050
public void updateAllocated(Long hostId, long allocatedAmount, short capacityType, boolean add) {
4151
Transaction txn = Transaction.currentTxn();
4252
PreparedStatement pstmt = null;
@@ -91,5 +101,13 @@ public void clearStorageCapacities() {
91101
txn.rollback();
92102
s_logger.warn("Exception clearing storage capacities", e);
93103
}
104+
}
105+
106+
@Override
107+
public CapacityVO findByHostIdType(Long hostId, short capacityType) {
108+
SearchCriteria<CapacityVO> sc = _hostIdTypeSearch.create();
109+
sc.setParameters("hostId", hostId);
110+
sc.setParameters("type", capacityType);
111+
return findOneBy(sc);
94112
}
95113
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package com.cloud.deploy;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
6+
import com.cloud.capacity.CapacityVO;
7+
import com.cloud.capacity.dao.CapacityDao;
8+
import com.cloud.dc.ClusterVO;
9+
import com.cloud.dc.DataCenter;
10+
import com.cloud.dc.HostPodVO;
11+
import com.cloud.dc.Pod;
12+
import com.cloud.dc.dao.ClusterDao;
13+
import com.cloud.dc.dao.DataCenterDao;
14+
import com.cloud.dc.dao.HostPodDao;
15+
import com.cloud.exception.InsufficientServerCapacityException;
16+
import com.cloud.host.Host;
17+
import com.cloud.host.HostVO;
18+
import com.cloud.host.Status;
19+
import com.cloud.host.dao.HostDao;
20+
import com.cloud.offering.ServiceOffering;
21+
import com.cloud.org.Cluster;
22+
import com.cloud.utils.component.Inject;
23+
import com.cloud.utils.db.Transaction;
24+
import com.cloud.vm.VirtualMachine;
25+
import com.cloud.vm.VirtualMachineProfile;
26+
27+
public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner {
28+
@Inject private HostDao _hostDao;
29+
@Inject private CapacityDao _capacityDao;
30+
@Inject private DataCenterDao _dcDao;
31+
@Inject private HostPodDao _podDao;
32+
@Inject private ClusterDao _clusterDao;
33+
34+
@Override
35+
public DeployDestination plan(VirtualMachineProfile vmProfile,
36+
DeploymentPlan plan, ExcludeList avoid)
37+
throws InsufficientServerCapacityException {
38+
VirtualMachine vm = vmProfile.getVirtualMachine();
39+
ServiceOffering offering = vmProfile.getServiceOffering();
40+
DataCenter dc = _dcDao.findById(vm.getDataCenterId());
41+
int cpu_requested = offering.getCpu() * offering.getSpeed();
42+
int ram_requested = offering.getRamSize();
43+
44+
if (vm.getLastHostId() != null) {
45+
HostVO host = _hostDao.findById(vm.getLastHostId());
46+
47+
if (host.getStatus() == Status.Up) {
48+
boolean canDepployToLastHost = deployToHost(vm.getLastHostId(), cpu_requested, ram_requested, true);
49+
if (canDepployToLastHost) {
50+
Pod pod = _podDao.findById(vm.getPodId());
51+
Cluster cluster = _clusterDao.findById(host.getClusterId());
52+
return new DeployDestination(dc, pod, cluster, host);
53+
}
54+
}
55+
}
56+
57+
/*Go through all the pods/clusters under zone*/
58+
List<HostPodVO> pods = _podDao.listByDataCenterId(plan.getDataCenterId());
59+
Collections.shuffle(pods);
60+
61+
for (HostPodVO hostPod : pods) {
62+
List<ClusterVO> clusters = _clusterDao.listByPodId(hostPod.getId());
63+
Collections.shuffle(clusters);
64+
65+
for (ClusterVO clusterVO : clusters) {
66+
List<HostVO> hosts = _hostDao.listByCluster(clusterVO.getId());
67+
Collections.shuffle(hosts);
68+
69+
for (HostVO hostVO : hosts) {
70+
if (hostVO.getStatus() != Status.Up) {
71+
continue;
72+
}
73+
74+
boolean canDeployToHost = deployToHost(hostVO.getId(), cpu_requested, ram_requested, false);
75+
if (canDeployToHost) {
76+
Pod pod = _podDao.findById(hostPod.getId());
77+
Cluster cluster = _clusterDao.findById(clusterVO.getId());
78+
Host host = _hostDao.findById(hostVO.getId());
79+
return new DeployDestination(dc, pod, cluster, host);
80+
}
81+
}
82+
}
83+
}
84+
85+
return null;
86+
}
87+
88+
private boolean deployToHost(Long hostId, Integer cpu, long ram, boolean fromLastHost) {
89+
90+
CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_CPU);
91+
CapacityVO capacityMem = _capacityDao.findByHostIdType(hostId, CapacityVO.CAPACITY_TYPE_MEMORY);
92+
93+
Transaction txn = Transaction.currentTxn();
94+
txn.start();
95+
96+
try {
97+
capacityCpu = _capacityDao.lockRow(capacityCpu.getId(), true);
98+
capacityMem = _capacityDao.lockRow(capacityMem.getId(), true);
99+
100+
long usedCpu = capacityCpu.getUsedCapacity();
101+
long usedMem = capacityMem.getUsedCapacity();
102+
long reservedCpu = capacityCpu.getReservedCapacity();
103+
long reservedMem = capacityMem.getReservedCapacity();
104+
long totalCpu = capacityCpu.getTotalCapacity();
105+
long totalMem = capacityMem.getTotalCapacity();
106+
107+
boolean success = false;
108+
if (fromLastHost) {
109+
/*alloc from reserved*/
110+
if (reservedCpu >= cpu && reservedMem >= ram) {
111+
capacityCpu.setReservedCapacity(reservedCpu - cpu);
112+
capacityMem.setReservedCapacity(reservedMem - ram);
113+
success = true;
114+
}
115+
} else {
116+
/*alloc from free resource*/
117+
if ((reservedCpu + usedCpu + cpu <= totalCpu) && (reservedMem + usedMem + ram <= totalMem)) {
118+
capacityCpu.setUsedCapacity(usedCpu + cpu);
119+
capacityMem.setUsedCapacity(totalMem + ram);
120+
success = true;
121+
}
122+
}
123+
124+
if (success) {
125+
_capacityDao.update(capacityCpu.getId(), capacityCpu);
126+
_capacityDao.update(capacityMem.getId(), capacityMem);
127+
}
128+
129+
return success;
130+
} finally {
131+
txn.commit();
132+
}
133+
134+
}
135+
@Override
136+
public boolean check(VirtualMachineProfile vm, DeploymentPlan plan,
137+
DeployDestination dest, ExcludeList exclude) {
138+
// TODO Auto-generated method stub
139+
return false;
140+
}
141+
142+
}

server/src/com/cloud/ha/HighAvailabilityManagerImpl.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import com.cloud.vm.VirtualMachine;
7272
import com.cloud.vm.VirtualMachine.Event;
7373
import com.cloud.vm.VirtualMachineManager;
74+
import com.cloud.vm.VmManager;
7475
import com.cloud.vm.dao.VMInstanceDao;
7576

7677
/**
@@ -130,6 +131,7 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
130131
@Inject StorageManager _storageMgr;
131132
@Inject GuestOSDao _guestOSDao;
132133
@Inject GuestOSCategoryDao _guestOSCategoryDao;
134+
@Inject VmManager _itMgr;
133135

134136
String _instance;
135137
ScheduledExecutorService _executor;
@@ -358,7 +360,8 @@ protected Long restart(final HaWorkVO work) {
358360
if (vm.getHostId() == null || vm.getHostId() != work.getHostId()) {
359361
s_logger.info("VM " + vm.toString() + " is now no longer on host " + work.getHostId());
360362
if (vm.getState() == State.Starting && vm.getUpdated() == work.getUpdateTime()) {
361-
_instanceDao.updateIf(vm, Event.AgentReportStopped, null);
363+
vm.setHostId(null);
364+
_itMgr.stateTransitTo(vm, Event.AgentReportStopped);
362365
}
363366
return null;
364367
}
@@ -518,7 +521,7 @@ protected Command compareState(VMInstanceVO vm, final AgentVmInfo info, final bo
518521
s_logger.debug("Both states are " + agentState.toString() + " for " + serverName);
519522
}
520523
assert (agentState == State.Stopped || agentState == State.Running) : "If the states we send up is changed, this must be changed.";
521-
_instanceDao.updateIf(vm, agentState == State.Stopped ? VirtualMachine.Event.AgentReportStopped : VirtualMachine.Event.AgentReportRunning, vm.getHostId());
524+
_itMgr.stateTransitTo(vm, agentState == State.Stopped ? VirtualMachine.Event.AgentReportStopped : VirtualMachine.Event.AgentReportRunning);
522525
if (agentState == State.Stopped) {
523526
s_logger.debug("State matches but the agent said stopped so let's send a cleanup anyways.");
524527
return info.mgr.cleanup(vm, agentName);
@@ -549,7 +552,8 @@ protected Command compareState(VMInstanceVO vm, final AgentVmInfo info, final bo
549552
s_logger.debug("Ignoring VM in starting mode: " + vm.getHostName());
550553
} else {
551554
s_logger.debug("Sending cleanup to a stopped vm: " + agentName);
552-
_instanceDao.updateIf(vm, VirtualMachine.Event.AgentReportStopped, null);
555+
vm.setHostId(null);
556+
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportStopped);
553557
command = info.mgr.cleanup(vm, agentName);
554558
}
555559
} else if (agentState == State.Running) {
@@ -573,7 +577,7 @@ protected Command compareState(VMInstanceVO vm, final AgentVmInfo info, final bo
573577
vm = info.mgr.get(vm.getId());
574578
command = info.mgr.cleanup(vm, agentName);
575579
} else {
576-
_instanceDao.updateIf(vm, VirtualMachine.Event.AgentReportRunning, vm.getHostId());
580+
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning);
577581
}
578582
} /*else if (agentState == State.Unknown) {
579583
if (serverState == State.Running) {
@@ -745,7 +749,7 @@ public Long migrate(final HaWorkVO work) {
745749
if (work.getStep() == Step.Migrating) {
746750
vm = mgr.get(vmId); // let's see if anything has changed.
747751
boolean migrated = false;
748-
if (vm == null || vm.getRemoved() != null || vm.getHostId() == null || !_instanceDao.updateIf(vm, Event.MigrationRequested, vm.getHostId())) {
752+
if (vm == null || vm.getRemoved() != null || vm.getHostId() == null || !_itMgr.stateTransitTo(vm, Event.MigrationRequested)) {
749753
s_logger.info("Migration cancelled because state has changed: " + vm.toString());
750754
} else {
751755
try {
@@ -775,7 +779,7 @@ public Long migrate(final HaWorkVO work) {
775779
HostPodVO podVO = _podDao.findById(vm.getPodId());
776780
_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.");
777781

778-
_instanceDao.updateIf(vm, Event.OperationFailed, vm.getHostId());
782+
_itMgr.stateTransitTo(vm, Event.OperationFailed);
779783
_agentMgr.maintenanceFailed(vm.getHostId());
780784

781785
Command cleanup = mgr.cleanup(vm, null);
@@ -805,7 +809,8 @@ public Long migrate(final HaWorkVO work) {
805809
} catch (final OperationTimedoutException e) {
806810
s_logger.warn("Operation timed outfor " + vm.toString());
807811
}
808-
_instanceDao.updateIf(vm, Event.OperationFailed, toHost.getId());
812+
vm.setHostId(toHost.getId());
813+
_itMgr.stateTransitTo(vm, Event.OperationFailed);
809814
return (System.currentTimeMillis() >> 10) + _migrateRetryInterval;
810815
}
811816

0 commit comments

Comments
 (0)