Adding new DeploymentClusterPlanner interface

This commit is contained in:
Prachi Damle 2013-04-24 15:40:39 -07:00
parent 06d4b7de3b
commit 1c5cddf084
4 changed files with 234 additions and 15 deletions

View File

@ -0,0 +1,45 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deploy;
import java.util.List;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
/**
*/
public interface DeploymentClusterPlanner extends DeploymentPlanner {
/**
* This is called to determine list of possible clusters where a virtual
* machine can be deployed.
*
* @param vm
* virtual machine.
* @param plan
* deployment plan that tells you where it's being deployed to.
* @param avoid
* avoid these data centers, pods, clusters, or hosts.
* @return DeployDestination for that virtual machine.
*/
List<Long> orderClusters(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan,
ExcludeList avoid) throws InsufficientServerCapacityException;
PlannerResourceUsage getResourceType();
}

View File

@ -35,6 +35,7 @@ import com.cloud.vm.VirtualMachineProfile;
/**
*/
public interface DeploymentPlanner extends Adapter {
/**
* plan is called to determine where a virtual machine should be running.
*
@ -46,6 +47,7 @@ public interface DeploymentPlanner extends Adapter {
* avoid these data centers, pods, clusters, or hosts.
* @return DeployDestination for that virtual machine.
*/
@Deprecated
DeployDestination plan(VirtualMachineProfile<? extends VirtualMachine> vm, DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException;
/**
@ -88,6 +90,10 @@ public interface DeploymentPlanner extends Adapter {
userconcentratedpod_firstfit;
}
public enum PlannerResourceUsage {
Shared, Dedicated;
}
public static class ExcludeList {
private Set<Long> _dcIds;
private Set<Long> _podIds;

View File

@ -17,9 +17,11 @@
package com.cloud.deploy;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
import org.apache.cloudstack.affinity.AffinityGroupVMMapVO;
@ -27,21 +29,44 @@ import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.log4j.Logger;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage;
import com.cloud.deploy.dao.PlannerHostReservationDao;
import com.cloud.exception.AffinityConflictException;
import com.cloud.exception.ConnectionException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.security.SecurityGroupVO;
import com.cloud.offering.ServiceOffering;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
import com.cloud.agent.api.AgentControlCommand;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
@Local(value = { DeploymentPlanningManager.class })
public class DeploymentPlanningManagerImpl extends ManagerBase implements DeploymentPlanningManager, Manager {
public class DeploymentPlanningManagerImpl extends ManagerBase implements DeploymentPlanningManager, Manager, Listener {
private static final Logger s_logger = Logger.getLogger(DeploymentPlanningManagerImpl.class);
@Inject
AgentManager _agentMgr;
@Inject
protected UserVmDao _vmDao;
@Inject
protected VMInstanceDao _vmInstanceDao;
@ -49,6 +74,10 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
protected AffinityGroupDao _affinityGroupDao;
@Inject
protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
@Inject
DataCenterDao _dcDao;
@Inject
PlannerHostReservationDao _plannerHostReserveDao;
protected List<DeploymentPlanner> _planners;
public List<DeploymentPlanner> getPlanners() {
@ -88,19 +117,162 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
// call planners
DeployDestination dest = null;
for (DeploymentPlanner planner : _planners) {
if (planner.canHandle(vmProfile, plan, avoids)) {
dest = planner.plan(vmProfile, plan, avoids);
} else {
continue;
}
if (dest != null) {
avoids.addHost(dest.getHost().getId());
break;
}
List<Long> clusterIds = null;
ServiceOffering offering = vmProfile.getServiceOffering();
if (offering != null && offering.getDeploymentPlanner() != null) {
DeploymentPlanner planner = ComponentContext.getComponent(offering.getDeploymentPlanner());
if (planner != null && planner.canHandle(vmProfile, plan, avoids)) {
while (true) {
if (planner instanceof DeploymentClusterPlanner) {
clusterIds = ((DeploymentClusterPlanner) planner).orderClusters(vmProfile, plan, avoids);
} else {
dest = planner.plan(vmProfile, plan, avoids);
}
if (dest != null) {
long hostId = dest.getHost().getId();
avoids.addHost(dest.getHost().getId());
if (checkIfHostCanBeUsed(hostId, DeploymentPlanner.PlannerResourceUsage.Shared)) {
// found destination
return dest;
} else {
// find another host - seems some concurrent deployment picked it up for dedicated access
continue;
}
} else if (clusterIds != null && !clusterIds.isEmpty()) {
// planner refactoring. call allocators to list hosts
} else {
return null;
}
}
}
}
return dest;
}
@DB
private boolean checkIfHostCanBeUsed(long hostId, PlannerResourceUsage resourceTypeRequired) {
// TODO Auto-generated method stub
// check if this host has been picked up by some other planner
// exclusively
// if planner can work with shared host, check if this host has
// been marked as 'shared'
// else if planner needs dedicated host,
PlannerHostReservationVO reservationEntry = _plannerHostReserveDao.findByHostId(hostId);
if (reservationEntry != null) {
long id = reservationEntry.getId();
PlannerResourceUsage hostResourceType = reservationEntry.getResourceUsage();
if (hostResourceType != null) {
if (hostResourceType == resourceTypeRequired) {
return true;
} else {
return false;
}
} else {
// reserve the host for required resourceType
// let us lock the reservation entry before updating.
final Transaction txn = Transaction.currentTxn();
try {
txn.start();
final PlannerHostReservationVO lockedEntry = _plannerHostReserveDao.lockRow(id, true);
if (lockedEntry == null) {
s_logger.error("Unable to lock the host entry for reservation, host: " + hostId);
return false;
}
// check before updating
if (lockedEntry.getResourceUsage() == null) {
lockedEntry.setResourceUsage(resourceTypeRequired);
_plannerHostReserveDao.persist(lockedEntry);
return true;
} else {
// someone updated it earlier. check if we can still use it
if (lockedEntry.getResourceUsage() == resourceTypeRequired) {
return true;
} else {
return false;
}
}
} finally {
txn.commit();
}
}
}
return false;
}
@Override
public boolean processAnswers(long agentId, long seq, Answer[] answers) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean processCommands(long agentId, long seq, Command[] commands) {
// TODO Auto-generated method stub
return false;
}
@Override
public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
if (!(cmd instanceof StartupRoutingCommand)) {
return;
}
PlannerHostReservationVO reservationEntry = _plannerHostReserveDao.findByHostId(host.getId());
if (reservationEntry == null) {
// record the host in this table
PlannerHostReservationVO newHost = new PlannerHostReservationVO(host.getId(), host.getDataCenterId(),
host.getPodId(), host.getClusterId());
_plannerHostReserveDao.persist(newHost);
}
}
@Override
public boolean processDisconnect(long agentId, Status state) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isRecurring() {
// TODO Auto-generated method stub
return false;
}
@Override
public int getTimeout() {
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean processTimeout(long agentId, long seq) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
_agentMgr.registerForHostEvents(this, true, false, true);
return super.configure(name, params);
}
}

View File

@ -97,7 +97,6 @@ import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeployPlannerSelector;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
@ -401,9 +400,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Inject
AffinityGroupDao _affinityGroupDao;
@Inject
List<DeployPlannerSelector> plannerSelectors;
protected ScheduledExecutorService _executor = null;
protected int _expungeInterval;
protected int _expungeDelay;