Bug 11522 - New agent manager

replace simulateStart with createHostAndAgent
This commit is contained in:
frank 2011-09-22 14:42:05 -07:00
parent 0677232e06
commit 0343cb79c3
13 changed files with 381 additions and 117 deletions

View File

@ -34,6 +34,7 @@ import com.cloud.host.Host.Type;
import com.cloud.resource.AgentResourceBase;
import com.cloud.resource.AgentRoutingResource;
import com.cloud.resource.AgentStorageResource;
import com.cloud.resource.ResourceManager;
import com.cloud.simulator.MockHost;
import com.cloud.simulator.MockHostVO;
import com.cloud.simulator.MockVMVO;
@ -56,6 +57,7 @@ public class MockAgentManagerImpl implements MockAgentManager {
@Inject SimulatorManager _simulatorMgr = null;
@Inject AgentManager _agentMgr = null;
@Inject MockStorageManager _storageMgr = null;
@Inject ResourceManager _resourceMgr;
private SecureRandom random;
private Map<String, AgentResourceBase> _resources = new ConcurrentHashMap<String, AgentResourceBase>();
private ThreadPoolExecutor _executor;
@ -270,7 +272,7 @@ public class MockAgentManagerImpl implements MockAgentManager {
}
Map<String, String> details = new HashMap<String, String>();
_agentMgr.addHost(this.dcId, storageResource, Type.SecondaryStorageVM, details);
_resourceMgr.addHost(this.dcId, storageResource, Type.SecondaryStorageVM, details);
_resources.put(this.guid, storageResource);
}

View File

@ -20,6 +20,7 @@ package com.cloud.host;
import java.util.Date;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceState;
import com.cloud.utils.fsm.StateObject;
@ -202,4 +203,7 @@ public interface Host extends StateObject<Status> {
String getHypervisorVersion();
boolean isInMaintenanceStates();
ResourceState getResourceState();
}

View File

@ -38,6 +38,7 @@ import javax.persistence.TemporalType;
import javax.persistence.Transient;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.resource.ResourceState;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.GenericDao;
@ -130,6 +131,10 @@ public class HostVO implements Host {
@Column(name="allocation_state", nullable=false)
@Enumerated(value=EnumType.STRING)
private HostAllocationState hostAllocationState;
@Column(name="resource_state", nullable=false)
@Enumerated(value=EnumType.STRING)
private ResourceState resourceState;
@Column(name="hypervisor_version")
private String hypervisorVersion;
@ -700,5 +705,16 @@ public class HostVO implements Host {
public Long getHostId() {
// TODO Auto-generated method stub
return null;
}
}
@Override
public ResourceState getResourceState() {
return resourceState;
}
@Override
public boolean isInMaintenanceStates() {
return (getResourceState() == ResourceState.Maintenance || getResourceState() == ResourceState.ErrorInMaintenance
|| getResourceState() == ResourceState.PrepareForMaintenace);
}
}

View File

@ -23,6 +23,7 @@ import java.util.Set;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.manager.AgentAttache;
import com.cloud.agent.manager.Commands;
import com.cloud.api.commands.UpdateHostPasswordCmd;
@ -30,6 +31,7 @@ import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodCluster;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConnectionException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
@ -53,6 +55,12 @@ public interface AgentManager extends Manager {
Continue, Stop
}
public enum TapAgentsAction {
Add,
Del,
Contains,
}
/**
* easy send method that returns null if there's any errors. It handles all exceptions.
*
@ -187,17 +195,6 @@ public interface AgentManager extends Manager {
List<PodCluster> listByPod(long podId);
/**
* Adds a new host
*
* @param zoneId
* @param resource
* @param hostType
* @param hostDetails
* @return new Host
*/
public Host addHost(long zoneId, ServerResource resource, Type hostType, Map<String, String> hostDetails);
/**
* Deletes a host
*
@ -250,8 +247,6 @@ public interface AgentManager extends Manager {
void notifyAnswersToMonitors(long agentId, long seq, Answer[] answers);
AgentAttache simulateStart(Long id, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags, String allocationState, boolean forRebalance) throws IllegalArgumentException;
boolean updateHostPassword(UpdateHostPasswordCmd upasscmd);
long sendToSecStorage(HostVO ssHost, Command cmd, Listener listener);
@ -261,5 +256,11 @@ public interface AgentManager extends Manager {
HostVO getSSAgent(HostVO ssHost);
void updateStatus(HostVO host, Event event);
/* working as a lock while agent is being loaded */
public boolean tapLoadingAgents(Long hostId, TapAgentsAction action);
public AgentAttache createAttacheForDirectConnect(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance) throws ConnectionException;
public boolean agentStatusTransitTo(HostVO host, Status.Event e, long msId);
}

View File

@ -117,6 +117,8 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase;
import com.cloud.network.IPAddressVO;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceState;
import com.cloud.resource.ServerResource;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.Storage;
@ -147,6 +149,8 @@ import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.exception.HypervisorVersionChangedException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.utils.net.Ip;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.nio.HandlerFactory;
@ -255,6 +259,10 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
protected AgentMonitor _monitor = null;
protected ExecutorService _executor;
protected StateMachine2<Status, Status.Event, Host> _statusStateMachine = Status.getStateMachine();
@Inject ResourceManager _resourceMgr;
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
@ -1275,12 +1283,8 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
}
if (forRebalance) {
AgentAttache attache = simulateStart(host.getId(), resource, host.getDetails(), false, null, null, true);
if (attache == null) {
return false;
} else {
return true;
}
Host h = _resourceMgr.createHostAndAgent(host.getId(), resource, host.getDetails(), false, null, null, true);
return (h == null ? false : true);
} else {
_executor.execute(new SimulateStartTask(host.getId(), resource, host.getDetails(), null));
return true;
@ -1288,69 +1292,32 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
}
@Override
public AgentAttache simulateStart(Long id, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags, String allocationState, boolean forRebalance) throws IllegalArgumentException {
HostVO host = null;
if (id != null) {
synchronized (_loadingAgents) {
s_logger.debug("Adding to loading agents " + id);
_loadingAgents.add(id);
}
public AgentAttache createAttacheForDirectConnect(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance)
throws ConnectionException {
if (resource instanceof DummySecondaryStorageResource || resource instanceof KvmDummyResourceBase) {
return new DummyAttache(this, host.getId(), false);
}
AgentAttache attache = null;
StartupCommand[] cmds = null;
try {
if (id != null) {
host = _hostDao.findById(id);
if (!_hostDao.directConnect(host, _nodeId)) {
s_logger.info("MS " + host.getManagementServerId() + " is loading " + host);
return null;
}
}
cmds = resource.initialize();
if (cmds == null) {
s_logger.info("Unable to fully initialize the agent because no StartupCommands are returned");
return null;
}
if (host != null) {
if (!_hostDao.directConnect(host, _nodeId)) {
host = _hostDao.findById(id);
s_logger.info("MS " + host.getManagementServerId() + " is loading " + host + " after it has been initialized.");
return null;
}
}
if (s_logger.isDebugEnabled()) {
new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true);
}
try {
attache = handleDirectConnect(resource, cmds, details, old, hostTags, allocationState, forRebalance);
} catch (IllegalArgumentException ex) {
s_logger.warn("Unable to connect due to ", ex);
throw ex;
} catch (Exception e) {
s_logger.warn("Unable to connect due to ", e);
}
} finally {
if (id != null) {
synchronized (_loadingAgents) {
_loadingAgents.remove(id);
}
}
if (attache == null) {
if (cmds != null) {
resource.disconnected();
}
if (host != null) {
_hostDao.updateStatus(host, Event.AgentDisconnected, _nodeId);
}
}
s_logger.debug("create DirectAgentAttache for " + host.getId());
DirectAgentAttache attache = new DirectAgentAttache(this, host.getId(), resource, host.isInMaintenanceStates(), this);
AgentAttache old = null;
synchronized (_agents) {
old = _agents.put(host.getId(), attache);
}
return attache;
if (old != null) {
old.disconnect(Status.Removed);
}
StartupAnswer[] answers = new StartupAnswer[cmds.length];
for (int i = 0; i < answers.length; i++) {
answers[i] = new StartupAnswer(cmds[i], attache.getId(), _pingInterval);
}
attache.process(answers);
return notifyMonitorsOfConnection(attache, cmds, forRebalance);
}
@Override
public boolean stop() {
if (_monitor != null) {
@ -1758,26 +1725,6 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
}
}
@Override
public Host addHost(long zoneId, ServerResource resource, Type hostType, Map<String, String> hostDetails) {
// Check if the zone exists in the system
if (_dcDao.findById(zoneId) == null) {
throw new InvalidParameterValueException("Can't find zone with id " + zoneId);
}
Map<String, String> details = hostDetails;
String guid = details.get("guid");
List<HostVO> currentHosts = _hostDao.listBy(hostType, zoneId);
for (HostVO currentHost : currentHosts) {
if (currentHost.getGuid().equals(guid)) {
return currentHost;
}
}
AgentAttache attache = simulateStart(null, resource, hostDetails, true, null, null, false);
return _hostDao.findById(attache.getId());
}
public HostVO createHost(final StartupCommand startup, ServerResource resource, Map<String, String> details, boolean directFirst, List<String> hostTags, String allocationState)
throws IllegalArgumentException {
Host.Type type = null;
@ -2207,7 +2154,8 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Simulating start for resource " + resource.getName() + " id " + id);
}
simulateStart(id, resource, details, false, null, null, false);
_resourceMgr.createHostAndAgent(id, resource, details, false, null, null, false);
} catch (Exception e) {
s_logger.warn("Unable to simulate start on resource " + id + " name " + resource.getName(), e);
} finally {
@ -2447,4 +2395,60 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager {
protected AgentManagerImpl() {
}
@Override
public boolean tapLoadingAgents(Long hostId, TapAgentsAction action) {
synchronized (_loadingAgents) {
if (action == TapAgentsAction.Add) {
_loadingAgents.add(hostId);
} else if (action == TapAgentsAction.Del) {
_loadingAgents.remove(hostId);
} else if (action == TapAgentsAction.Contains) {
return _loadingAgents.contains(hostId);
} else {
throw new CloudRuntimeException("Unkonwn TapAgentsAction " + action);
}
}
return true;
}
private boolean isAgentEventAllowedByResourceState(HostVO host, Status.Event event) {
ResourceState state = host.getResourceState();
boolean allow = true;
if (state == ResourceState.Enabled) {
} else if (state == ResourceState.Disabled) {
if (event == Status.Event.AgentConnected) {
allow = false;
}
} else if (state == ResourceState.Unmanaged) {
if (event == Status.Event.AgentConnected) {
allow = false;
}
} else if (state == ResourceState.PrepareForMaintenace) {
} else if (state == ResourceState.Maintenance) {
} else {
throw new CloudRuntimeException("Unknown resource state " + state);
}
return allow;
}
@Override
public boolean agentStatusTransitTo(HostVO host, Status.Event e, long msId) {
if (!isAgentEventAllowedByResourceState(host, e)) {
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()));
return false;
}
host.setManagementServerId(msId);
try {
return _statusStateMachine.transitTo(host, e, host.getId(), _hostDao);
} catch (NoTransitionException e1) {
s_logger.debug("Cannot transit agent status with event " + e + " for host " + host.getId() + ", mangement server id is " + msId);
throw new CloudRuntimeException("Cannot transit agent status with event " + e + " for host " + host.getId() + ", mangement server id is " + msId + "," + e1.getMessage());
}
}
}

View File

@ -39,8 +39,10 @@ import com.cloud.deploy.DeployDestination;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Inject;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
@ -51,6 +53,7 @@ import com.cloud.vm.VirtualMachineProfile;
@Local(value=PxeServerService.class)
public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements PxeServerService {
private static final Logger s_logger = Logger.getLogger(BareMetalPingServiceImpl.class);
@Inject ResourceManager _resourceMgr;
@Override
public Host addPxeServer(PxeServerProfile profile) {
@ -122,7 +125,7 @@ public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements
throw new CloudRuntimeException("Unsupport PXE server type:" + profile.getType());
}
Host pxeServer = _agentMgr.addHost(zoneId, resource, Host.Type.PxeServer, params);
Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.PxeServer, params);
if (pxeServer == null) {
throw new CloudRuntimeException("Cannot add PXE server as a host");
}

View File

@ -59,6 +59,7 @@ import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.utils.component.Inject;
import com.cloud.utils.concurrency.NamedThreadFactory;
@ -81,6 +82,7 @@ public class ExternalDhcpManagerImpl implements ExternalDhcpManager {
@Inject AgentManager _agentMgr;
@Inject HostPodDao _podDao;
@Inject UserVmDao _userVmDao;
@Inject ResourceManager _resourceMgr;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
@ -159,7 +161,7 @@ public class ExternalDhcpManagerImpl implements ExternalDhcpManager {
throw new CloudRuntimeException(e.getMessage());
}
Host dhcpServer = _agentMgr.addHost(zoneId, resource, Host.Type.ExternalDhcp, params);
Host dhcpServer = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalDhcp, params);
if (dhcpServer == null) {
throw new CloudRuntimeException("Cannot add external Dhcp server as a host");
}

View File

@ -93,6 +93,7 @@ import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.server.api.response.ExternalFirewallResponse;
import com.cloud.server.api.response.ExternalLoadBalancerResponse;
@ -147,6 +148,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager {
@Inject VpnUserDao _vpnUsersDao;
@Inject InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao;
@Inject AccountManager _accountMgr;
@Inject ResourceManager _resourceMgr;
ScheduledExecutorService _executor;
int _externalNetworkStatsInterval;
@ -285,7 +287,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager {
throw new CloudRuntimeException(e.getMessage());
}
Host host = _agentMgr.addHost(zoneId, resource, Host.Type.ExternalLoadBalancer, hostDetails);
Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalLoadBalancer, hostDetails);
if (host != null) {
if (deviceType.equalsIgnoreCase(ExternalNetworkDeviceType.F5BigIP.getName())) {
zone.setLoadBalancerProvider(Network.Provider.F5BigIp.getName());
@ -630,7 +632,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager {
throw new CloudRuntimeException(e.getMessage());
}
Host externalFirewall = _agentMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, hostDetails);
Host externalFirewall = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, hostDetails);
if (externalFirewall != null) {
zone.setFirewallProvider(Network.Provider.JuniperSRX.getName());
zone.setUserDataProvider(Network.Provider.DhcpServer.getName());

2
server/src/com/cloud/network/F5BigIpManagerImpl.java Normal file → Executable file
View File

@ -141,7 +141,7 @@ public class F5BigIpManagerImpl extends ExternalNetworkManagerImpl implements Ex
throw new CloudRuntimeException(e.getMessage());
}
Host host = _agentMgr.addHost(zoneId, resource, Host.Type.ExternalLoadBalancer, hostDetails);
Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalLoadBalancer, hostDetails);
if (host != null) {
zone.setLoadBalancerProvider(Network.Provider.F5BigIp.getName());
_dcDao.update(zone.getId(), zone);

View File

@ -43,6 +43,7 @@ import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.PortForwardingRule;
import com.cloud.network.rules.StaticNatRule;
import com.cloud.offering.NetworkOffering;
import com.cloud.resource.ResourceManager;
import com.cloud.server.api.response.ExternalFirewallResponse;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
@ -78,6 +79,8 @@ public class JuniperSrxManagerImpl extends ExternalNetworkManagerImpl implements
ConfigurationManager _configMgr;
@Inject
AccountManager _accountMgr;
@Inject
ResourceManager _resourceMgr;
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(JuniperSrxManagerImpl.class);
@ -184,7 +187,7 @@ public class JuniperSrxManagerImpl extends ExternalNetworkManagerImpl implements
throw new CloudRuntimeException(e.getMessage());
}
Host externalFirewall = _agentMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, hostDetails);
Host externalFirewall = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, hostDetails);
if (externalFirewall != null) {
zone.setFirewallProvider(Network.Provider.JuniperSRX.getName());
zone.setUserDataProvider(Network.Provider.DhcpServer.getName());

View File

@ -66,6 +66,7 @@ import com.cloud.network.Network.GuestIpType;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.resource.TrafficSentinelResource;
import com.cloud.resource.ResourceManager;
import com.cloud.server.api.response.TrafficMonitorResponse;
import com.cloud.usage.UsageIPAddressVO;
import com.cloud.user.AccountManager;
@ -104,6 +105,7 @@ public class NetworkUsageManagerImpl implements NetworkUsageManager {
@Inject HostDetailsDao _detailsDao;
@Inject AccountManager _accountMgr;
@Inject NetworkDao _networksDao = null;
@Inject ResourceManager _resourceMgr;
ScheduledExecutorService _executor;
int _networkStatsInterval;
protected SearchBuilder<IPAddressVO> AllocatedIpSearch;
@ -161,7 +163,7 @@ public class NetworkUsageManagerImpl implements NetworkUsageManager {
hostDetails.put("url", cmd.getUrl());
hostDetails.put("last_collection", ""+System.currentTimeMillis());
Host trafficMonitor = _agentMgr.addHost(zoneId, resource, Host.Type.TrafficMonitor, hostDetails);
Host trafficMonitor = _resourceMgr.addHost(zoneId, resource, Host.Type.TrafficMonitor, hostDetails);
return trafficMonitor;
}

View File

@ -17,7 +17,11 @@
*/
package com.cloud.resource;
import java.util.List;
import java.util.Map;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
/**
* ResourceManager manages how physical resources are organized within the
@ -45,4 +49,9 @@ public interface ResourceManager {
public void registerResourceStateAdapter(String name, ResourceStateAdapter adapter);
public void unregisterResourceStateAdapter(String name);
public Host createHostAndAgent(Long hostId, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags,
String allocationState, boolean forRebalance);
public Host addHost(long zoneId, ServerResource resource, Type hostType, Map<String, String> hostDetails);
}

View File

@ -33,8 +33,10 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.AgentManager.TapAgentsAction;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.manager.AgentAttache;
import com.cloud.agent.transport.Request;
import com.cloud.api.commands.AddClusterCmd;
import com.cloud.api.commands.AddHostCmd;
import com.cloud.api.commands.AddSecondaryStorageCmd;
@ -58,6 +60,7 @@ import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.host.Host;
import com.cloud.host.Host.HostAllocationState;
import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
@ -85,6 +88,7 @@ import com.cloud.utils.component.Manager;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
@Local({ ResourceManager.class, ResourceService.class })
public class ResourceManagerImpl implements ResourceManager, ResourceService, Manager {
@ -364,9 +368,9 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
break;
}
AgentAttache attache = _agentMgr.simulateStart(null, resource, entry.getValue(), true, null, null, false);
if (attache != null) {
hosts.add(_hostDao.findById(attache.getId()));
HostVO host = (HostVO)createHostAndAgent(resource, entry.getValue(), true, null, null, false);
if (host != null) {
hosts.add(host);
}
discoverer.postDiscovery(hosts, _nodeId);
}
@ -585,9 +589,10 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
}
return null;
}
AgentAttache attache = _agentMgr.simulateStart(null, resource, entry.getValue(), true, hostTags, allocationState, false);
if (attache != null) {
hosts.add(_hostDao.findById(attache.getId()));
HostVO host = (HostVO)createHostAndAgent(resource, entry.getValue(), true, hostTags, allocationState, false);
if (host != null) {
hosts.add(host);
}
discoverer.postDiscovery(hosts, _nodeId);
@ -1030,6 +1035,217 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma
return result;
}
}
private boolean checkCIDR(HostPodVO pod, String serverPrivateIP, String serverPrivateNetmask) {
if (serverPrivateIP == null) {
return true;
}
// Get the CIDR address and CIDR size
String cidrAddress = pod.getCidrAddress();
long cidrSize = pod.getCidrSize();
// If the server's private IP address is not in the same subnet as the
// pod's CIDR, return false
String cidrSubnet = NetUtils.getCidrSubNet(cidrAddress, cidrSize);
String serverSubnet = NetUtils.getSubNet(serverPrivateIP, serverPrivateNetmask);
if (!cidrSubnet.equals(serverSubnet)) {
return false;
}
// If the server's private netmask is less inclusive than the pod's CIDR
// netmask, return false
String cidrNetmask = NetUtils.getCidrSubNet("255.255.255.255", cidrSize);
long cidrNetmaskNumeric = NetUtils.ip2Long(cidrNetmask);
long serverNetmaskNumeric = NetUtils.ip2Long(serverPrivateNetmask);
if (serverNetmaskNumeric > cidrNetmaskNumeric) {
return false;
}
return true;
}
protected HostVO createHostVO(StartupCommand[] cmds, ServerResource resource, Map<String, String> details, List<String> hostTags,
ResourceStateAdapter.Event stateEvent) {
StartupCommand startup = cmds[0];
HostVO host = _hostDao.findByGuid(startup.getGuid());
if (host == null) {
host = _hostDao.findByGuid(startup.getGuidWithoutResource());
}
if (host == null) {
host = new HostVO(startup.getGuid());
host.setResource(resource.getClass().getName());
host = _hostDao.persist(host);
}
// TODO: we don't allow to set ResourceState here?
String dataCenter = startup.getDataCenter();
String pod = startup.getPod();
String cluster = startup.getCluster();
if (pod != null && dataCenter != null && pod.equalsIgnoreCase("default") && dataCenter.equalsIgnoreCase("default")) {
List<HostPodVO> pods = _podDao.listAllIncludingRemoved();
for (HostPodVO hpv : pods) {
if (checkCIDR(hpv, startup.getPrivateIpAddress(), startup.getPrivateNetmask())) {
pod = hpv.getName();
dataCenter = _dcDao.findById(hpv.getDataCenterId()).getName();
break;
}
}
}
long dcId = -1;
DataCenterVO dc = _dcDao.findByName(dataCenter);
if (dc == null) {
try {
dcId = Long.parseLong(dataCenter);
dc = _dcDao.findById(dcId);
} catch (final NumberFormatException e) {
}
}
if (dc == null) {
throw new IllegalArgumentException("Host " + startup.getPrivateIpAddress() + " sent incorrect data center: " + dataCenter);
}
dcId = dc.getId();
HostPodVO p = _podDao.findByName(pod, dcId);
if (p == null) {
try {
final long podId = Long.parseLong(pod);
p = _podDao.findById(podId);
} catch (final NumberFormatException e) {
}
}
/*
* ResourceStateAdapter is responsible for throwing Exception if Pod is
* null and non-null is required. for example, XcpServerDiscoever.
* Others, like PxeServer, ExternalFireware don't require Pod
*/
Long podId = (p == null ? null : p.getId());
Long clusterId = null;
if (cluster != null) {
try {
clusterId = Long.valueOf(cluster);
} catch (NumberFormatException e) {
ClusterVO c = _clusterDao.findBy(cluster, podId);
if (c == null) {
c = new ClusterVO(dcId, podId, cluster);
c = _clusterDao.persist(c);
}
clusterId = c.getId();
}
}
host.setDataCenterId(dc.getId());
host.setPodId(podId);
host.setClusterId(clusterId);
host.setPrivateIpAddress(startup.getPrivateIpAddress());
host.setPrivateNetmask(startup.getPrivateNetmask());
host.setPrivateMacAddress(startup.getPrivateMacAddress());
host.setPublicIpAddress(startup.getPublicIpAddress());
host.setPublicMacAddress(startup.getPublicMacAddress());
host.setPublicNetmask(startup.getPublicNetmask());
host.setStorageIpAddress(startup.getStorageIpAddress());
host.setStorageMacAddress(startup.getStorageMacAddress());
host.setStorageNetmask(startup.getStorageNetmask());
host.setVersion(startup.getVersion());
host.setName(startup.getName());
host.setManagementServerId(_nodeId);
host.setStorageUrl(startup.getIqn());
host.setLastPinged(System.currentTimeMillis() >> 10);
host.setHostTags(hostTags);
host.setDetails(details);
if (startup.getStorageIpAddressDeux() != null) {
host.setStorageIpAddressDeux(startup.getStorageIpAddressDeux());
host.setStorageMacAddressDeux(startup.getStorageMacAddressDeux());
host.setStorageNetmaskDeux(startup.getStorageNetmaskDeux());
}
host = (HostVO) dispatchToStateAdapters(stateEvent, true, host, cmds, resource, details, hostTags);
_hostDao.update(host.getId(), host);
/* Agent goes to Connecting status */
_agentMgr.agentStatusTransitTo(host, Status.Event.AgentConnected, _nodeId);
return host;
}
private Host createHostAndAgent(ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags, String allocationState,
boolean forRebalance) {
HostVO host = null;
AgentAttache attache = null;
StartupCommand[] cmds = null;
try {
cmds = resource.initialize();
if (cmds == null) {
s_logger.info("Unable to fully initialize the agent because no StartupCommands are returned");
return null;
}
if (s_logger.isDebugEnabled()) {
new Request(-1l, -1l, cmds, true, false).logD("Startup request from directly connected host: ", true);
}
if (old) {
StartupCommand firstCmd = cmds[0];
host = _hostDao.findByGuid(firstCmd.getGuid());
if (host == null) {
host = _hostDao.findByGuid(firstCmd.getGuidWithoutResource());
}
if (host != null && host.getRemoved() == null) {
s_logger.debug("Found the host " + host.getId() + " by guid: " + firstCmd.getGuid() + ", old host reconnected as new");
return null;
}
}
host = createHostVO(cmds, resource, details, hostTags, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT);
if (host != null) {
attache = _agentMgr.createAttacheForDirectConnect(host, cmds, resource, forRebalance);
/* reload myself from database */
host = _hostDao.findById(host.getId());
}
} catch (Exception e) {
s_logger.warn("Unable to connect due to ", e);
} finally {
if (attache == null) {
if (cmds != null) {
resource.disconnected();
}
if (host != null) {
/* Change agent status to Alert */
_agentMgr.agentStatusTransitTo(host, Status.Event.AgentDisconnected, _nodeId);
}
}
}
return host;
}
@Override
public Host createHostAndAgent(Long hostId, ServerResource resource, Map<String, String> details, boolean old, List<String> hostTags,
String allocationState, boolean forRebalance) {
_agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Add);
Host host = createHostAndAgent(resource, details, old, hostTags, allocationState, forRebalance);
_agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Del);
return host;
}
@Override
public Host addHost(long zoneId, ServerResource resource, Type hostType, Map<String, String> hostDetails) {
// Check if the zone exists in the system
if (_dcDao.findById(zoneId) == null) {
throw new InvalidParameterValueException("Can't find zone with id " + zoneId);
}
Map<String, String> details = hostDetails;
String guid = details.get("guid");
List<HostVO> currentHosts = _hostDao.listBy(hostType, zoneId);
for (HostVO currentHost : currentHosts) {
if (currentHost.getGuid().equals(guid)) {
return currentHost;
}
}
return createHostAndAgent(resource, hostDetails, true, null, null, false);
}
}