From f63e412ac9fc9b1162eb2d6725eb2d7d9175f26d Mon Sep 17 00:00:00 2001 From: frank Date: Fri, 23 Sep 2011 15:22:39 -0700 Subject: [PATCH] Bug 11522 - New agent manager moves migration to ResourceManager --- server/src/com/cloud/agent/AgentManager.java | 2 + .../cloud/agent/manager/AgentManagerImpl.java | 10 +++ server/src/com/cloud/host/dao/HostDao.java | 5 +- .../src/com/cloud/host/dao/HostDaoImpl.java | 30 ++++++++ .../com/cloud/resource/ResourceManager.java | 4 ++ .../cloud/resource/ResourceManagerImpl.java | 68 ++++++++++++++++++- 6 files changed, 117 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/agent/AgentManager.java b/server/src/com/cloud/agent/AgentManager.java index 03940a692c8..21d56da7699 100755 --- a/server/src/com/cloud/agent/AgentManager.java +++ b/server/src/com/cloud/agent/AgentManager.java @@ -257,4 +257,6 @@ public interface AgentManager extends Manager { void disconnect(long hostId, Status.Event event); public boolean disconnectAgent(HostVO host, Status.Event e, long msId); + + public void pullAgentToMaintenance(long hostId); } diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index f516e4a1380..6e7bb5e9a28 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -2277,4 +2277,14 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { return attache; } + + @Override + public void pullAgentToMaintenance(long hostId) { + AgentAttache attache = findAttache(hostId); + if (attache != null) { + attache.setMaintenanceMode(true); + // Now cancel all of the commands except for the active one. + attache.cancelAllCommands(Status.Disconnected, false); + } + } } diff --git a/server/src/com/cloud/host/dao/HostDao.java b/server/src/com/cloud/host/dao/HostDao.java index fb5dbf64fee..8ad61d79838 100755 --- a/server/src/com/cloud/host/dao/HostDao.java +++ b/server/src/com/cloud/host/dao/HostDao.java @@ -27,6 +27,7 @@ import com.cloud.host.Status; import com.cloud.host.Status.Event; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.info.RunningHostCountInfo; +import com.cloud.resource.ResourceState; import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; @@ -179,5 +180,7 @@ public interface HostDao extends GenericDao, StateDao listByInAllStatus(Type type, Long clusterId, Long podId, long dcId); - List listByClusterStatus(long clusterId, Status status); + List listByClusterStatus(long clusterId, Status status); + + boolean updateResourceState(ResourceState oldState, ResourceState.Event event, ResourceState newState, Host vo); } diff --git a/server/src/com/cloud/host/dao/HostDaoImpl.java b/server/src/com/cloud/host/dao/HostDaoImpl.java index 3744131d9ec..b39f2408e2d 100755 --- a/server/src/com/cloud/host/dao/HostDaoImpl.java +++ b/server/src/com/cloud/host/dao/HostDaoImpl.java @@ -45,6 +45,7 @@ import com.cloud.host.Status.Event; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.info.RunningHostCountInfo; import com.cloud.org.Managed; +import com.cloud.resource.ResourceState; import com.cloud.utils.DateUtil; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.Attribute; @@ -1082,5 +1083,34 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao return result > 0; } + + @Override + public boolean updateResourceState(ResourceState oldState, ResourceState.Event event, ResourceState newState, Host vo) { + HostVO host = (HostVO)vo; + SearchBuilder sb = createSearchBuilder(); + sb.and("resource_state", sb.entity().getResourceState(), SearchCriteria.Op.EQ); + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + sb.done(); + + SearchCriteria sc = sb.create(); + + sc.setParameters("status", oldState); + sc.setParameters("id", host.getId()); + + UpdateBuilder ub = getUpdateBuilder(host); + ub.set(host, _statusAttr, newState); + int result = update(ub, sc, null); + assert result <= 1 : "How can this update " + result + " rows? "; + + if (s_logger.isDebugEnabled() && result == 0) { + HostVO ho = findById(host.getId()); + assert ho != null : "How how how? : " + host.getId(); + + StringBuilder str = new StringBuilder("Unable to update resource state for event:").append(event.toString()); + /*TODO: add defbug info*/ + } + + return result > 0; + } } diff --git a/server/src/com/cloud/resource/ResourceManager.java b/server/src/com/cloud/resource/ResourceManager.java index fc5cd96afc4..ba167bb7369 100755 --- a/server/src/com/cloud/resource/ResourceManager.java +++ b/server/src/com/cloud/resource/ResourceManager.java @@ -29,6 +29,8 @@ import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.host.HostVO; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceState.Event; +import com.cloud.utils.fsm.NoTransitionException; /** * ResourceManager manages how physical resources are organized within the @@ -71,4 +73,6 @@ public interface ResourceManager { public void deleteRoutingHost(HostVO host, boolean isForced, boolean forceDestroyStorage) throws UnableDeleteHostException; public boolean executeUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException; + + boolean updateResourceState(Host host, Event event, long msId) throws NoTransitionException; } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index c8f9ac62cc0..14f115f0443 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -34,6 +34,8 @@ import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager.TapAgentsAction; +import com.cloud.agent.api.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.manager.AgentAttache; @@ -66,6 +68,7 @@ import com.cloud.exception.DiscoveryException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.ha.HighAvailabilityManager; +import com.cloud.ha.HighAvailabilityManager.WorkType; import com.cloud.host.Host; import com.cloud.host.Host.HostAllocationState; import com.cloud.host.Host.Type; @@ -106,6 +109,7 @@ import com.cloud.utils.db.DB; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; import com.cloud.vm.VMInstanceVO; @@ -966,6 +970,68 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma throw new CloudRuntimeException("Failed to reconnect host with id " + hostId.toString() + ", internal error."); } + @Override + public boolean updateResourceState(Host host, ResourceState.Event event, long msId) throws NoTransitionException { + ResourceState currentState = host.getResourceState(); + ResourceState nextState = currentState.getNextState(event); + if (nextState == null) { + throw new NoTransitionException("No next resource state found for current state =" + currentState + " event =" + event); + } + + /*TODO: adding debug trace*/ + return _hostDao.updateResourceState(currentState, event, nextState, host); + } + + private boolean doMaintain(final long hostId) { + HostVO host = _hostDao.findById(hostId); + MaintainAnswer answer = (MaintainAnswer) _agentMgr.easySend(hostId, new MaintainCommand()); + if (answer == null || !answer.getResult()) { + s_logger.warn("Unable to put host in maintainance mode: " + hostId); + return false; + } + + try { + updateResourceState(host, ResourceState.Event.AdminAskMaintenace, _nodeId); + } catch (NoTransitionException e) { + String err = "Cannot transimit resource state of host " + host.getId() + " to " + ResourceState.Maintenance; + s_logger.debug(err, e); + throw new CloudRuntimeException(err + e.getMessage()); + } + + _agentMgr.pullAgentToMaintenance(hostId); + + /*TODO: move below to listener */ + if (host.getType() == Host.Type.Routing) { + + final List vms = _vmDao.listByHostId(hostId); + if (vms.size() == 0) { + return true; + } + + List hosts = _hostDao.listBy(host.getClusterId(), host.getPodId(), host.getDataCenterId()); + + for (final VMInstanceVO vm : vms) { + if (hosts == null || hosts.size() <= 1 || !answer.getMigrate()) { + // for the last host in this cluster, stop all the VMs + _haMgr.scheduleStop(vm, hostId, WorkType.ForceStop); + } else { + _haMgr.scheduleMigration(vm); + } + } + } + + return true; + } + + private boolean maintain(final long hostId) throws AgentUnavailableException { + Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.AdminAskMaintenace); + if (result != null) { + return result; + } + + return doMaintain(hostId); + } + @Override public Host maintain(PrepareForMaintenanceCmd cmd) { Long hostId = cmd.getId(); @@ -986,7 +1052,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma try { processResourceEvent(ResourceListener.EVENT_PREPARE_MAINTENANCE_BEFORE, hostId); - if (_agentMgr.maintain(hostId)) { + if (maintain(hostId)) { processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, hostId); return _hostDao.findById(hostId); } else {