Skip to content

Commit 0343cb7

Browse files
committed
Bug 11522 - New agent manager
replace simulateStart with createHostAndAgent
1 parent 0677232 commit 0343cb7

13 files changed

Lines changed: 380 additions & 116 deletions

File tree

agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java

100644100755
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.cloud.resource.AgentResourceBase;
3535
import com.cloud.resource.AgentRoutingResource;
3636
import com.cloud.resource.AgentStorageResource;
37+
import com.cloud.resource.ResourceManager;
3738
import com.cloud.simulator.MockHost;
3839
import com.cloud.simulator.MockHostVO;
3940
import com.cloud.simulator.MockVMVO;
@@ -56,6 +57,7 @@ public class MockAgentManagerImpl implements MockAgentManager {
5657
@Inject SimulatorManager _simulatorMgr = null;
5758
@Inject AgentManager _agentMgr = null;
5859
@Inject MockStorageManager _storageMgr = null;
60+
@Inject ResourceManager _resourceMgr;
5961
private SecureRandom random;
6062
private Map<String, AgentResourceBase> _resources = new ConcurrentHashMap<String, AgentResourceBase>();
6163
private ThreadPoolExecutor _executor;
@@ -270,7 +272,7 @@ public void run() {
270272
}
271273
Map<String, String> details = new HashMap<String, String>();
272274

273-
_agentMgr.addHost(this.dcId, storageResource, Type.SecondaryStorageVM, details);
275+
_resourceMgr.addHost(this.dcId, storageResource, Type.SecondaryStorageVM, details);
274276
_resources.put(this.guid, storageResource);
275277
}
276278

api/src/com/cloud/host/Host.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Date;
2121

2222
import com.cloud.hypervisor.Hypervisor.HypervisorType;
23+
import com.cloud.resource.ResourceState;
2324
import com.cloud.utils.fsm.StateObject;
2425

2526

@@ -202,4 +203,7 @@ public enum HostAllocationState {
202203

203204
String getHypervisorVersion();
204205

206+
boolean isInMaintenanceStates();
207+
208+
ResourceState getResourceState();
205209
}

core/src/com/cloud/host/HostVO.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import javax.persistence.Transient;
3939

4040
import com.cloud.hypervisor.Hypervisor.HypervisorType;
41+
import com.cloud.resource.ResourceState;
4142
import com.cloud.storage.Storage.StoragePoolType;
4243
import com.cloud.utils.NumbersUtil;
4344
import com.cloud.utils.db.GenericDao;
@@ -130,6 +131,10 @@ public class HostVO implements Host {
130131
@Column(name="allocation_state", nullable=false)
131132
@Enumerated(value=EnumType.STRING)
132133
private HostAllocationState hostAllocationState;
134+
135+
@Column(name="resource_state", nullable=false)
136+
@Enumerated(value=EnumType.STRING)
137+
private ResourceState resourceState;
133138

134139
@Column(name="hypervisor_version")
135140
private String hypervisorVersion;
@@ -700,5 +705,16 @@ public Status getState() {
700705
public Long getHostId() {
701706
// TODO Auto-generated method stub
702707
return null;
703-
}
708+
}
709+
710+
@Override
711+
public ResourceState getResourceState() {
712+
return resourceState;
713+
}
714+
715+
@Override
716+
public boolean isInMaintenanceStates() {
717+
return (getResourceState() == ResourceState.Maintenance || getResourceState() == ResourceState.ErrorInMaintenance
718+
|| getResourceState() == ResourceState.PrepareForMaintenace);
719+
}
704720
}

server/src/com/cloud/agent/AgentManager.java

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@
2323

2424
import com.cloud.agent.api.Answer;
2525
import com.cloud.agent.api.Command;
26+
import com.cloud.agent.api.StartupCommand;
2627
import com.cloud.agent.manager.AgentAttache;
2728
import com.cloud.agent.manager.Commands;
2829
import com.cloud.api.commands.UpdateHostPasswordCmd;
2930
import com.cloud.dc.DataCenterVO;
3031
import com.cloud.dc.HostPodVO;
3132
import com.cloud.dc.PodCluster;
3233
import com.cloud.exception.AgentUnavailableException;
34+
import com.cloud.exception.ConnectionException;
3335
import com.cloud.exception.OperationTimedoutException;
3436
import com.cloud.host.Host;
3537
import com.cloud.host.Host.Type;
@@ -53,6 +55,12 @@ public enum OnError {
5355
Continue, Stop
5456
}
5557

58+
public enum TapAgentsAction {
59+
Add,
60+
Del,
61+
Contains,
62+
}
63+
5664
/**
5765
* easy send method that returns null if there's any errors. It handles all exceptions.
5866
*
@@ -187,17 +195,6 @@ public enum OnError {
187195

188196
List<PodCluster> listByPod(long podId);
189197

190-
/**
191-
* Adds a new host
192-
*
193-
* @param zoneId
194-
* @param resource
195-
* @param hostType
196-
* @param hostDetails
197-
* @return new Host
198-
*/
199-
public Host addHost(long zoneId, ServerResource resource, Type hostType, Map<String, String> hostDetails);
200-
201198
/**
202199
* Deletes a host
203200
*
@@ -250,8 +247,6 @@ public enum OnError {
250247

251248
void notifyAnswersToMonitors(long agentId, long seq, Answer[] answers);
252249

253-
AgentAttache simulateStart(Long id, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags, String allocationState, boolean forRebalance) throws IllegalArgumentException;
254-
255250
boolean updateHostPassword(UpdateHostPasswordCmd upasscmd);
256251

257252
long sendToSecStorage(HostVO ssHost, Command cmd, Listener listener);
@@ -261,5 +256,11 @@ public enum OnError {
261256
HostVO getSSAgent(HostVO ssHost);
262257

263258
void updateStatus(HostVO host, Event event);
264-
259+
260+
/* working as a lock while agent is being loaded */
261+
public boolean tapLoadingAgents(Long hostId, TapAgentsAction action);
262+
263+
public AgentAttache createAttacheForDirectConnect(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance) throws ConnectionException;
264+
265+
public boolean agentStatusTransitTo(HostVO host, Status.Event e, long msId);
265266
}

server/src/com/cloud/agent/manager/AgentManagerImpl.java

Lines changed: 90 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@
117117
import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase;
118118
import com.cloud.network.IPAddressVO;
119119
import com.cloud.network.dao.IPAddressDao;
120+
import com.cloud.resource.ResourceManager;
121+
import com.cloud.resource.ResourceState;
120122
import com.cloud.resource.ServerResource;
121123
import com.cloud.service.ServiceOfferingVO;
122124
import com.cloud.storage.Storage;
@@ -147,6 +149,8 @@
147149
import com.cloud.utils.db.Transaction;
148150
import com.cloud.utils.exception.CloudRuntimeException;
149151
import com.cloud.utils.exception.HypervisorVersionChangedException;
152+
import com.cloud.utils.fsm.NoTransitionException;
153+
import com.cloud.utils.fsm.StateMachine2;
150154
import com.cloud.utils.net.Ip;
151155
import com.cloud.utils.net.NetUtils;
152156
import com.cloud.utils.nio.HandlerFactory;
@@ -255,6 +259,10 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
255259
protected AgentMonitor _monitor = null;
256260

257261
protected ExecutorService _executor;
262+
263+
protected StateMachine2<Status, Status.Event, Host> _statusStateMachine = Status.getStateMachine();
264+
265+
@Inject ResourceManager _resourceMgr;
258266

259267
@Override
260268
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
@@ -1275,82 +1283,41 @@ protected boolean loadDirectlyConnectedHost(HostVO host, boolean forRebalance) {
12751283
}
12761284

12771285
if (forRebalance) {
1278-
AgentAttache attache = simulateStart(host.getId(), resource, host.getDetails(), false, null, null, true);
1279-
if (attache == null) {
1280-
return false;
1281-
} else {
1282-
return true;
1283-
}
1286+
Host h = _resourceMgr.createHostAndAgent(host.getId(), resource, host.getDetails(), false, null, null, true);
1287+
return (h == null ? false : true);
12841288
} else {
12851289
_executor.execute(new SimulateStartTask(host.getId(), resource, host.getDetails(), null));
12861290
return true;
12871291
}
12881292
}
12891293

12901294
@Override
1291-
public AgentAttache simulateStart(Long id, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags, String allocationState, boolean forRebalance) throws IllegalArgumentException {
1292-
HostVO host = null;
1293-
if (id != null) {
1294-
synchronized (_loadingAgents) {
1295-
s_logger.debug("Adding to loading agents " + id);
1296-
_loadingAgents.add(id);
1297-
}
1295+
public AgentAttache createAttacheForDirectConnect(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance)
1296+
throws ConnectionException {
1297+
if (resource instanceof DummySecondaryStorageResource || resource instanceof KvmDummyResourceBase) {
1298+
return new DummyAttache(this, host.getId(), false);
1299+
}
1300+
1301+
s_logger.debug("create DirectAgentAttache for " + host.getId());
1302+
DirectAgentAttache attache = new DirectAgentAttache(this, host.getId(), resource, host.isInMaintenanceStates(), this);
1303+
1304+
AgentAttache old = null;
1305+
synchronized (_agents) {
1306+
old = _agents.put(host.getId(), attache);
1307+
}
1308+
if (old != null) {
1309+
old.disconnect(Status.Removed);
12981310
}
1299-
AgentAttache attache = null;
1300-
StartupCommand[] cmds = null;
1301-
try {
1302-
if (id != null) {
1303-
host = _hostDao.findById(id);
1304-
if (!_hostDao.directConnect(host, _nodeId)) {
1305-
s_logger.info("MS " + host.getManagementServerId() + " is loading " + host);
1306-
return null;
1307-
}
1308-
}
1309-
1310-
cmds = resource.initialize();
1311-
if (cmds == null) {
1312-
s_logger.info("Unable to fully initialize the agent because no StartupCommands are returned");
1313-
return null;
1314-
}
1315-
1316-
if (host != null) {
1317-
if (!_hostDao.directConnect(host, _nodeId)) {
1318-
host = _hostDao.findById(id);
1319-
s_logger.info("MS " + host.getManagementServerId() + " is loading " + host + " after it has been initialized.");
1320-
return null;
1321-
}
1322-
}
1323-
1324-
if (s_logger.isDebugEnabled()) {
1325-
new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true);
1326-
}
1327-
try {
1328-
attache = handleDirectConnect(resource, cmds, details, old, hostTags, allocationState, forRebalance);
1329-
} catch (IllegalArgumentException ex) {
1330-
s_logger.warn("Unable to connect due to ", ex);
1331-
throw ex;
1332-
} catch (Exception e) {
1333-
s_logger.warn("Unable to connect due to ", e);
1334-
}
13351311

1336-
} finally {
1337-
if (id != null) {
1338-
synchronized (_loadingAgents) {
1339-
_loadingAgents.remove(id);
1340-
}
1341-
}
1342-
if (attache == null) {
1343-
if (cmds != null) {
1344-
resource.disconnected();
1345-
}
1346-
if (host != null) {
1347-
_hostDao.updateStatus(host, Event.AgentDisconnected, _nodeId);
1348-
}
1349-
}
1312+
StartupAnswer[] answers = new StartupAnswer[cmds.length];
1313+
for (int i = 0; i < answers.length; i++) {
1314+
answers[i] = new StartupAnswer(cmds[i], attache.getId(), _pingInterval);
13501315
}
1351-
return attache;
1352-
}
1316+
attache.process(answers);
13531317

1318+
return notifyMonitorsOfConnection(attache, cmds, forRebalance);
1319+
}
1320+
13541321
@Override
13551322
public boolean stop() {
13561323
if (_monitor != null) {
@@ -1758,26 +1725,6 @@ public void checkIPConflicts(Host.Type type, HostPodVO pod, DataCenterVO dc, Str
17581725
}
17591726
}
17601727

1761-
@Override
1762-
public Host addHost(long zoneId, ServerResource resource, Type hostType, Map<String, String> hostDetails) {
1763-
// Check if the zone exists in the system
1764-
if (_dcDao.findById(zoneId) == null) {
1765-
throw new InvalidParameterValueException("Can't find zone with id " + zoneId);
1766-
}
1767-
1768-
Map<String, String> details = hostDetails;
1769-
String guid = details.get("guid");
1770-
List<HostVO> currentHosts = _hostDao.listBy(hostType, zoneId);
1771-
for (HostVO currentHost : currentHosts) {
1772-
if (currentHost.getGuid().equals(guid)) {
1773-
return currentHost;
1774-
}
1775-
}
1776-
1777-
AgentAttache attache = simulateStart(null, resource, hostDetails, true, null, null, false);
1778-
return _hostDao.findById(attache.getId());
1779-
}
1780-
17811728
public HostVO createHost(final StartupCommand startup, ServerResource resource, Map<String, String> details, boolean directFirst, List<String> hostTags, String allocationState)
17821729
throws IllegalArgumentException {
17831730
Host.Type type = null;
@@ -2207,7 +2154,8 @@ public void run() {
22072154
if (s_logger.isDebugEnabled()) {
22082155
s_logger.debug("Simulating start for resource " + resource.getName() + " id " + id);
22092156
}
2210-
simulateStart(id, resource, details, false, null, null, false);
2157+
2158+
_resourceMgr.createHostAndAgent(id, resource, details, false, null, null, false);
22112159
} catch (Exception e) {
22122160
s_logger.warn("Unable to simulate start on resource " + id + " name " + resource.getName(), e);
22132161
} finally {
@@ -2447,4 +2395,60 @@ protected void doTask(final Task task) throws Exception {
24472395
protected AgentManagerImpl() {
24482396
}
24492397

2398+
@Override
2399+
public boolean tapLoadingAgents(Long hostId, TapAgentsAction action) {
2400+
synchronized (_loadingAgents) {
2401+
if (action == TapAgentsAction.Add) {
2402+
_loadingAgents.add(hostId);
2403+
} else if (action == TapAgentsAction.Del) {
2404+
_loadingAgents.remove(hostId);
2405+
} else if (action == TapAgentsAction.Contains) {
2406+
return _loadingAgents.contains(hostId);
2407+
} else {
2408+
throw new CloudRuntimeException("Unkonwn TapAgentsAction " + action);
2409+
}
2410+
}
2411+
return true;
2412+
}
2413+
2414+
private boolean isAgentEventAllowedByResourceState(HostVO host, Status.Event event) {
2415+
ResourceState state = host.getResourceState();
2416+
boolean allow = true;
2417+
if (state == ResourceState.Enabled) {
2418+
2419+
} else if (state == ResourceState.Disabled) {
2420+
if (event == Status.Event.AgentConnected) {
2421+
allow = false;
2422+
}
2423+
} else if (state == ResourceState.Unmanaged) {
2424+
if (event == Status.Event.AgentConnected) {
2425+
allow = false;
2426+
}
2427+
} else if (state == ResourceState.PrepareForMaintenace) {
2428+
2429+
} else if (state == ResourceState.Maintenance) {
2430+
2431+
} else {
2432+
throw new CloudRuntimeException("Unknown resource state " + state);
2433+
}
2434+
2435+
return allow;
2436+
}
2437+
2438+
@Override
2439+
public boolean agentStatusTransitTo(HostVO host, Status.Event e, long msId) {
2440+
if (!isAgentEventAllowedByResourceState(host, e)) {
2441+
s_logger.debug(String.format("Cannot proceed agent event %1$s because it is not allowed by current resource state %2$s fort host %3$s", e, host.getResourceState(), host.getId()));
2442+
return false;
2443+
}
2444+
2445+
host.setManagementServerId(msId);
2446+
try {
2447+
return _statusStateMachine.transitTo(host, e, host.getId(), _hostDao);
2448+
} catch (NoTransitionException e1) {
2449+
s_logger.debug("Cannot transit agent status with event " + e + " for host " + host.getId() + ", mangement server id is " + msId);
2450+
throw new CloudRuntimeException("Cannot transit agent status with event " + e + " for host " + host.getId() + ", mangement server id is " + msId + "," + e1.getMessage());
2451+
}
2452+
}
2453+
24502454
}

0 commit comments

Comments
 (0)