diff --git a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java old mode 100644 new mode 100755 index 5fcdff62648..7c7cf75ce09 --- a/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java +++ b/agent-simulator/src/com/cloud/agent/manager/MockAgentManagerImpl.java @@ -24,6 +24,7 @@ import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.GetHostStatsAnswer; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.HostStatsEntry; +import com.cloud.agent.api.MaintainAnswer; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PrepareForMigrationAnswer; import com.cloud.agent.api.PrepareForMigrationCommand; @@ -34,6 +35,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 +58,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 _resources = new ConcurrentHashMap(); private ThreadPoolExecutor _executor; @@ -270,7 +273,7 @@ public class MockAgentManagerImpl implements MockAgentManager { } Map details = new HashMap(); - _agentMgr.addHost(this.dcId, storageResource, Type.SecondaryStorageVM, details); + _resourceMgr.addHost(this.dcId, storageResource, Type.SecondaryStorageVM, details); _resources.put(this.guid, storageResource); } @@ -347,7 +350,7 @@ public class MockAgentManagerImpl implements MockAgentManager { @Override - public Answer MaintainCommand(com.cloud.agent.api.MaintainCommand cmd) { - return new Answer(cmd); + public MaintainAnswer MaintainCommand(com.cloud.agent.api.MaintainCommand cmd) { + return new MaintainAnswer(cmd); } } diff --git a/agent-simulator/src/com/cloud/agent/manager/SimulatorManager.java b/agent-simulator/src/com/cloud/agent/manager/SimulatorManager.java old mode 100644 new mode 100755 diff --git a/agent-simulator/src/com/cloud/api/commands/ConfigureSimulator.java b/agent-simulator/src/com/cloud/api/commands/ConfigureSimulator.java old mode 100644 new mode 100755 diff --git a/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java b/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java index dff0cce760d..df37cf98726 100755 --- a/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java +++ b/agent-simulator/src/com/cloud/resource/SimulatorDiscoverer.java @@ -38,6 +38,7 @@ 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; import com.cloud.agent.manager.MockAgentManager; import com.cloud.agent.manager.MockStorageManager; import com.cloud.agent.manager.SimulatorManager; @@ -66,7 +67,7 @@ import com.cloud.utils.component.Inject; * */ @Local(value = Discoverer.class) -public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, Listener { +public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter { private static final Logger s_logger = Logger .getLogger(SimulatorDiscoverer.class); @@ -78,6 +79,7 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L @Inject AgentManager _agentMgr = null; @Inject MockAgentManager _mockAgentMgr = null; @Inject MockStorageManager _mockStorageMgr = null; + @Inject ResourceManager _resourceMgr; /** * Finds ServerResources of an in-process simulator @@ -243,7 +245,8 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); - _agentMgr.registerForHostEvents(this, true, false, false); + _agentMgr.registerForHostEvents(this, true, false, false); + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -304,5 +307,42 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L public boolean processTimeout(long agentId, long seq) { return false; } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, + StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, + StartupCommand[] startup, ServerResource resource, + Map details, List hostTags) { + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupRoutingCommand)) { + return null; + } + + StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd); + if (ssCmd.getHypervisorType() != HypervisorType.Simulator) { + return null; + } + + return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.Simulator, details, hostTags); + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, + boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); + return super.stop(); + } } \ No newline at end of file diff --git a/api/src/com/cloud/agent/api/PropagateResourceEventCommand.java b/api/src/com/cloud/agent/api/PropagateResourceEventCommand.java new file mode 100755 index 00000000000..0c91c0eb150 --- /dev/null +++ b/api/src/com/cloud/agent/api/PropagateResourceEventCommand.java @@ -0,0 +1,32 @@ +package com.cloud.agent.api; + +import com.cloud.resource.ResourceState; + +public class PropagateResourceEventCommand extends Command { + long hostId; + ResourceState.Event event; + + protected PropagateResourceEventCommand() { + + } + + public PropagateResourceEventCommand(long hostId, ResourceState.Event event) { + this.hostId = hostId; + this.event = event; + } + + public long getHostId() { + return hostId; + } + + public ResourceState.Event getEvent() { + return event; + } + + @Override + public boolean executeInSequence() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/api/src/com/cloud/api/commands/ReconnectHostCmd.java b/api/src/com/cloud/api/commands/ReconnectHostCmd.java old mode 100644 new mode 100755 index 332d422c240..0c7d3b13b15 --- a/api/src/com/cloud/api/commands/ReconnectHostCmd.java +++ b/api/src/com/cloud/api/commands/ReconnectHostCmd.java @@ -107,7 +107,7 @@ public class ReconnectHostCmd extends BaseAsyncCmd { } else { throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to reconnect host"); } - } catch (AgentUnavailableException ex) { + } catch (Exception ex) { s_logger.warn("Exception: ", ex); throw new ServerApiException(BaseCmd.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } diff --git a/api/src/com/cloud/api/response/BaseResponse.java b/api/src/com/cloud/api/response/BaseResponse.java old mode 100644 new mode 100755 diff --git a/api/src/com/cloud/host/Host.java b/api/src/com/cloud/host/Host.java index 7cd674c0aba..97139bff227 100755 --- a/api/src/com/cloud/host/Host.java +++ b/api/src/com/cloud/host/Host.java @@ -20,12 +20,14 @@ 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; /** * Host represents one particular host server. */ -public interface Host { +public interface Host extends StateObject { public enum Type { Storage(false), Routing(false), @@ -58,11 +60,6 @@ public interface Host { } } - public enum HostAllocationState { - Disabled, - Enabled; - } - /** * @return id of the host. */ @@ -197,8 +194,9 @@ public interface Host { String getStorageMacAddressDeux(); - HostAllocationState getHostAllocationState(); - String getHypervisorVersion(); + boolean isInMaintenanceStates(); + + ResourceState getResourceState(); } diff --git a/api/src/com/cloud/host/Status.java b/api/src/com/cloud/host/Status.java old mode 100644 new mode 100755 index c915eb6a0cb..f1e024ed041 --- a/api/src/com/cloud/host/Status.java +++ b/api/src/com/cloud/host/Status.java @@ -20,19 +20,19 @@ package com.cloud.host; import java.util.List; import java.util.Set; +import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine; +import com.cloud.utils.fsm.StateMachine2; public enum Status { + Creating(true, false, false), Connecting(true, false, false), Up(true, false, false), Down(true, true, true), Disconnected(true, true, true), - Updating(true, true, false), - PrepareForMaintenance(false, false, false), - ErrorInMaintenance(false, false, false), - Maintenance(false, false, false), Alert(true, true, true), Removed(true, false, true), + Error(true, false, true), Rebalancing(false, false, false); private final boolean updateManagementServer; @@ -60,26 +60,19 @@ public enum Status { public enum Event { AgentConnected(false, "Agent connected"), PingTimeout(false, "Agent is behind on ping"), - UpdateNeeded(false, "UpdateRequested"), ShutdownRequested(false, "Shutdown requested by the agent"), AgentDisconnected(false, "Agent disconnected"), - ResetRequested(true, "Reset is requested by the user"), HostDown(false, "Host is found to be down by the investigator"), - PreparationComplete(false, "Preparation for PrepareForMaintenance is completed"), - UnableToMigrate(false, "Migration for at least one VM didn't work"), Ping(false, "Ping is received from the host"), - MaintenanceRequested(true, "PrepareForMaintenance requested by user"), ManagementServerDown(false, "Management Server that the agent is connected is going down"), WaitedTooLong(false, "Waited too long from the agent to reconnect on its own. Time to do HA"), Remove(true, "Host is removed"), Ready(false, "Host is ready for commands"), - UpdatePassword(false, "Update host password from db"), RequestAgentRebalance(false, "Request rebalance for the certain host"), StartAgentRebalance(false, "Start rebalance for the certain host"), RebalanceCompleted(false, "Host is rebalanced successfully"), RebalanceFailed(false, "Failed to rebalance the host"), - PrepareUnmanaged(true, "prepare for cluster entering unmanaged status"), - HypervisorVersionChanged(false, " hypervisor version changed when host is reconnected"); + Error(false, "An internal error happened"); private final boolean isUserRequest; private final String comment; @@ -97,7 +90,11 @@ public enum Status { } } - public Status getNextStatus(Event e) { + public static StateMachine2 getStateMachine() { + return s_fsm; + } + + public Status getNextStatus(Event e) throws NoTransitionException { return s_fsm.getNextState(this, e); } @@ -118,22 +115,20 @@ public enum Status { return strs; } - protected static final StateMachine s_fsm = new StateMachine(); + protected static final StateMachine2 s_fsm = new StateMachine2(); static { s_fsm.addTransition(null, Event.AgentConnected, Status.Connecting); + s_fsm.addTransition(Status.Creating, Event.AgentConnected, Status.Connecting); + s_fsm.addTransition(Status.Creating, Event.Error, Status.Error); s_fsm.addTransition(Status.Connecting, Event.AgentConnected, Status.Connecting); s_fsm.addTransition(Status.Connecting, Event.Ready, Status.Up); s_fsm.addTransition(Status.Connecting, Event.PingTimeout, Status.Alert); - s_fsm.addTransition(Status.Connecting, Event.UpdateNeeded, Status.Updating); - s_fsm.addTransition(Status.Connecting, Event.MaintenanceRequested, Status.PrepareForMaintenance); s_fsm.addTransition(Status.Connecting, Event.ShutdownRequested, Status.Disconnected); s_fsm.addTransition(Status.Connecting, Event.HostDown, Status.Alert); s_fsm.addTransition(Status.Connecting, Event.Ping, Status.Connecting); s_fsm.addTransition(Status.Connecting, Event.ManagementServerDown, Status.Disconnected); s_fsm.addTransition(Status.Connecting, Event.AgentDisconnected, Status.Alert); - s_fsm.addTransition(Status.Connecting, Event.HypervisorVersionChanged, Status.Disconnected); s_fsm.addTransition(Status.Up, Event.PingTimeout, Status.Alert); - s_fsm.addTransition(Status.Up, Event.MaintenanceRequested, Status.PrepareForMaintenance); s_fsm.addTransition(Status.Up, Event.AgentDisconnected, Status.Alert); s_fsm.addTransition(Status.Up, Event.ShutdownRequested, Status.Disconnected); s_fsm.addTransition(Status.Up, Event.HostDown, Status.Down); @@ -141,59 +136,28 @@ public enum Status { s_fsm.addTransition(Status.Up, Event.AgentConnected, Status.Connecting); s_fsm.addTransition(Status.Up, Event.ManagementServerDown, Status.Disconnected); s_fsm.addTransition(Status.Up, Event.StartAgentRebalance, Status.Rebalancing); - s_fsm.addTransition(Status.Up, Event.PrepareUnmanaged, Status.Disconnected); - s_fsm.addTransition(Status.Up, Event.HypervisorVersionChanged, Status.Disconnected); - s_fsm.addTransition(Status.Updating, Event.PingTimeout, Status.Alert); - s_fsm.addTransition(Status.Updating, Event.Ping, Status.Updating); - s_fsm.addTransition(Status.Updating, Event.AgentConnected, Status.Connecting); - s_fsm.addTransition(Status.Updating, Event.ManagementServerDown, Status.Disconnected); - s_fsm.addTransition(Status.Updating, Event.WaitedTooLong, Status.Alert); - s_fsm.addTransition(Status.PrepareForMaintenance, Event.ResetRequested, Status.Disconnected); - s_fsm.addTransition(Status.PrepareForMaintenance, Event.PreparationComplete, Status.Maintenance); - s_fsm.addTransition(Status.PrepareForMaintenance, Event.AgentDisconnected, Status.PrepareForMaintenance); - s_fsm.addTransition(Status.PrepareForMaintenance, Event.AgentConnected, Status.PrepareForMaintenance); - s_fsm.addTransition(Status.PrepareForMaintenance, Event.HostDown, Status.PrepareForMaintenance); - s_fsm.addTransition(Status.PrepareForMaintenance, Event.UnableToMigrate, Status.ErrorInMaintenance); - s_fsm.addTransition(Status.PrepareForMaintenance, Event.Ping, Status.PrepareForMaintenance); - s_fsm.addTransition(Status.PrepareForMaintenance, Event.ManagementServerDown, Status.PrepareForMaintenance); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.MaintenanceRequested, Status.PrepareForMaintenance); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.ResetRequested, Status.Disconnected); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.HostDown, Status.ErrorInMaintenance); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.AgentDisconnected, Status.ErrorInMaintenance); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.AgentConnected, Status.ErrorInMaintenance); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.Remove, Status.Removed); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.UnableToMigrate, Status.ErrorInMaintenance); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.PreparationComplete, Status.Maintenance); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.Ping, Status.ErrorInMaintenance); - s_fsm.addTransition(Status.ErrorInMaintenance, Event.ManagementServerDown, Status.ErrorInMaintenance); - s_fsm.addTransition(Status.Maintenance, Event.ResetRequested, Status.Disconnected); - s_fsm.addTransition(Status.Maintenance, Event.AgentDisconnected, Status.Maintenance); - s_fsm.addTransition(Status.Maintenance, Event.HostDown, Status.Maintenance); - s_fsm.addTransition(Status.Maintenance, Event.Remove, Status.Removed); - s_fsm.addTransition(Status.Maintenance, Event.AgentConnected, Status.Maintenance); - s_fsm.addTransition(Status.Maintenance, Event.Ping, Status.Maintenance); - s_fsm.addTransition(Status.Maintenance, Event.ManagementServerDown, Status.Maintenance); s_fsm.addTransition(Status.Disconnected, Event.PingTimeout, Status.Alert); s_fsm.addTransition(Status.Disconnected, Event.AgentConnected, Status.Connecting); s_fsm.addTransition(Status.Disconnected, Event.Ping, Status.Up); + s_fsm.addTransition(Status.Disconnected, Event.HostDown, Status.Down); s_fsm.addTransition(Status.Disconnected, Event.ManagementServerDown, Status.Disconnected); s_fsm.addTransition(Status.Disconnected, Event.WaitedTooLong, Status.Alert); s_fsm.addTransition(Status.Disconnected, Event.Remove, Status.Removed); - s_fsm.addTransition(Status.Disconnected, Event.HypervisorVersionChanged, Status.Disconnected); s_fsm.addTransition(Status.Disconnected, Event.AgentDisconnected, Status.Disconnected); - s_fsm.addTransition(Status.Down, Event.MaintenanceRequested, Status.PrepareForMaintenance); s_fsm.addTransition(Status.Down, Event.AgentConnected, Status.Connecting); s_fsm.addTransition(Status.Down, Event.Remove, Status.Removed); s_fsm.addTransition(Status.Down, Event.ManagementServerDown, Status.Down); s_fsm.addTransition(Status.Down, Event.AgentDisconnected, Status.Down); - s_fsm.addTransition(Status.Alert, Event.MaintenanceRequested, Status.PrepareForMaintenance); s_fsm.addTransition(Status.Alert, Event.AgentConnected, Status.Connecting); s_fsm.addTransition(Status.Alert, Event.Ping, Status.Up); s_fsm.addTransition(Status.Alert, Event.Remove, Status.Removed); s_fsm.addTransition(Status.Alert, Event.ManagementServerDown, Status.Alert); s_fsm.addTransition(Status.Alert, Event.AgentDisconnected, Status.Alert); + s_fsm.addTransition(Status.Alert, Event.ShutdownRequested, Status.Disconnected); s_fsm.addTransition(Status.Rebalancing, Event.RebalanceFailed, Status.Disconnected); s_fsm.addTransition(Status.Rebalancing, Event.RebalanceCompleted, Status.Connecting); + s_fsm.addTransition(Status.Rebalancing, Event.AgentConnected, Status.Connecting); + s_fsm.addTransition(Status.Error, Event.AgentConnected, Status.Connecting); } public static void main(String[] args) { diff --git a/api/src/com/cloud/resource/ResourceService.java b/api/src/com/cloud/resource/ResourceService.java old mode 100644 new mode 100755 index d6e5ca9aa8e..dcc56ce5643 --- a/api/src/com/cloud/resource/ResourceService.java +++ b/api/src/com/cloud/resource/ResourceService.java @@ -46,7 +46,7 @@ public interface ResourceService { Host cancelMaintenance(CancelMaintenanceCmd cmd); - Host reconnectHost(ReconnectHostCmd cmd) throws AgentUnavailableException; + Host reconnectHost(ReconnectHostCmd cmd); /** * We will automatically create a cloud.com cluster to attach to the external cluster and return a hyper host to perform diff --git a/api/src/com/cloud/resource/ResourceState.java b/api/src/com/cloud/resource/ResourceState.java new file mode 100755 index 00000000000..7d423b3ae8c --- /dev/null +++ b/api/src/com/cloud/resource/ResourceState.java @@ -0,0 +1,101 @@ +package com.cloud.resource; + +import java.util.List; +import java.util.Set; + +import com.cloud.utils.fsm.StateMachine; + +public enum ResourceState { + Creating, + Enabled, + Disabled, + Unmanaged, + PrepareForMaintenance, + ErrorInMaintenance, + Maintenance, + Error; + + public enum Event { + InternalCreated("Resource is created"), + Enable("Admin enables"), + Disable("Admin disables"), + AdminAskMaintenace("Admin asks to enter maintenance"), + AdminCancelMaintenance("Admin asks to cancel maintenance"), + InternalEnterMaintenance("Resource enters maintenance"), + Unmanaged("Admin turns a host into umanaged state"), + UpdatePassword("Admin updates password of host"), + UnableToMigrate("Management server migrates VM failed"), + Error("An internal error happened"), + DeleteHost("Admin delete a host"); + + private final String comment; + private Event(String comment) { + this.comment = comment; + } + + public String getDescription() { + return this.comment; + } + } + + public ResourceState getNextState(Event a) { + return s_fsm.getNextState(this, a); + } + + public ResourceState[] getFromStates(Event a) { + List from = s_fsm.getFromStates(this, a); + return from.toArray(new ResourceState[from.size()]); + } + + public Set getPossibleEvents() { + return s_fsm.getPossibleEvents(this); + } + + public static String[] toString(ResourceState... states) { + String[] strs = new String[states.length]; + for (int i=0; i s_fsm = new StateMachine(); + static { + s_fsm.addTransition(null, Event.InternalCreated, ResourceState.Enabled); + s_fsm.addTransition(ResourceState.Creating, Event.InternalCreated, ResourceState.Enabled); + s_fsm.addTransition(ResourceState.Creating, Event.Unmanaged, ResourceState.Enabled); + s_fsm.addTransition(ResourceState.Creating, Event.Error, ResourceState.Error); + s_fsm.addTransition(ResourceState.Enabled, Event.Enable, ResourceState.Enabled); + s_fsm.addTransition(ResourceState.Enabled, Event.InternalCreated, ResourceState.Enabled); + s_fsm.addTransition(ResourceState.Enabled, Event.Disable, ResourceState.Disabled); + s_fsm.addTransition(ResourceState.Enabled, Event.Unmanaged, ResourceState.Unmanaged); + s_fsm.addTransition(ResourceState.Enabled, Event.AdminAskMaintenace, ResourceState.PrepareForMaintenance); + //s_fsm.addTransition(ResourceState.Enabled, Event.Error, ResourceState.Error); + s_fsm.addTransition(ResourceState.Disabled, Event.Enable, ResourceState.Enabled); + s_fsm.addTransition(ResourceState.Disabled, Event.Disable, ResourceState.Disabled); + s_fsm.addTransition(ResourceState.Disabled, Event.InternalCreated, ResourceState.Disabled); + s_fsm.addTransition(ResourceState.Disabled, Event.Unmanaged, ResourceState.Unmanaged); + //s_fsm.addTransition(ResourceState.Disabled, Event.Error, ResourceState.Error); + s_fsm.addTransition(ResourceState.Unmanaged, Event.Unmanaged, ResourceState.Unmanaged); + s_fsm.addTransition(ResourceState.Unmanaged, Event.InternalCreated, ResourceState.Unmanaged); + //s_fsm.addTransition(ResourceState.Unmanaged, Event.Error, ResourceState.Error); + s_fsm.addTransition(ResourceState.PrepareForMaintenance, Event.InternalEnterMaintenance, ResourceState.Maintenance); + s_fsm.addTransition(ResourceState.PrepareForMaintenance, Event.AdminCancelMaintenance, ResourceState.Enabled); + s_fsm.addTransition(ResourceState.PrepareForMaintenance, Event.Unmanaged, ResourceState.Unmanaged); + //s_fsm.addTransition(ResourceState.PrepareForMaintenance, Event.Error, ResourceState.Error); + s_fsm.addTransition(ResourceState.PrepareForMaintenance, Event.UnableToMigrate, ResourceState.ErrorInMaintenance); + s_fsm.addTransition(ResourceState.PrepareForMaintenance, Event.InternalCreated, ResourceState.PrepareForMaintenance); + s_fsm.addTransition(ResourceState.Maintenance, Event.AdminCancelMaintenance, ResourceState.Enabled); + s_fsm.addTransition(ResourceState.Maintenance, Event.InternalCreated, ResourceState.Maintenance); + s_fsm.addTransition(ResourceState.Maintenance, Event.DeleteHost, ResourceState.Disabled); + s_fsm.addTransition(ResourceState.Maintenance, Event.Unmanaged, ResourceState.Unmanaged); + //s_fsm.addTransition(ResourceState.Maintenance, Event.Error, ResourceState.Error); + s_fsm.addTransition(ResourceState.ErrorInMaintenance, Event.Unmanaged, ResourceState.Unmanaged); + s_fsm.addTransition(ResourceState.ErrorInMaintenance, Event.InternalCreated, ResourceState.ErrorInMaintenance); + s_fsm.addTransition(ResourceState.ErrorInMaintenance, Event.Disable, ResourceState.Disabled); + s_fsm.addTransition(ResourceState.ErrorInMaintenance, Event.DeleteHost, ResourceState.Disabled); + s_fsm.addTransition(ResourceState.ErrorInMaintenance, Event.InternalEnterMaintenance, ResourceState.Maintenance); + //s_fsm.addTransition(ResourceState.ErrorInMaintenance, Event.Error, ResourceState.Error); + s_fsm.addTransition(ResourceState.Error, Event.InternalCreated, ResourceState.Error); + } +} diff --git a/build/developer.xml b/build/developer.xml index 8b78d4e5020..c5c6b3e26ef 100755 --- a/build/developer.xml +++ b/build/developer.xml @@ -242,11 +242,11 @@ - + - + @@ -362,11 +362,6 @@ - - - - - diff --git a/core/src/com/cloud/host/HostVO.java b/core/src/com/cloud/host/HostVO.java old mode 100644 new mode 100755 index 37593111571..a87a7ee3faa --- a/core/src/com/cloud/host/HostVO.java +++ b/core/src/com/cloud/host/HostVO.java @@ -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; @@ -126,13 +127,16 @@ public class HostVO implements Host { @Column(name="setup") private boolean setup = false; - - @Column(name="allocation_state", nullable=false) + + @Column(name="resource_state", nullable=false) @Enumerated(value=EnumType.STRING) - private HostAllocationState hostAllocationState; + private ResourceState resourceState; @Column(name="hypervisor_version") private String hypervisorVersion; + + @Column(name="update_count", updatable = true, nullable=false) + protected long updated; // This field should be updated everytime the state is updated. There's no set method in the vo object because it is done with in the dao code. // This is a delayed load value. If the value is null, // then this field has not been loaded yet. @@ -356,10 +360,10 @@ public class HostVO implements Host { public HostVO(String guid) { this.guid = guid; - this.status = Status.Up; + this.status = Status.Creating; this.totalMemory = 0; this.dom0MinMemory = 0; - this.hostAllocationState = Host.HostAllocationState.Enabled; + this.resourceState = ResourceState.Creating; } protected HostVO() { @@ -395,8 +399,7 @@ public class HostVO implements Host { this(id, name, type, privateIpAddress, privateNetmask, privateMacAddress, publicIpAddress, publicNetmask, publicMacAddress, storageIpAddress, storageNetmask, storageMacAddress, guid, status, version, iqn, disconnectedOn, dcId, podId, serverId, ping, null, null, null, 0, null); this.parent = parent; this.totalSize = totalSize; - this.fsType = fsType; - this.hostAllocationState = Host.HostAllocationState.Enabled; + this.fsType = fsType; } public HostVO(long id, @@ -453,8 +456,7 @@ public class HostVO implements Host { this.caps = caps; this.disconnectedOn = disconnectedOn; this.dom0MinMemory = dom0MinMemory; - this.storageUrl = url; - this.hostAllocationState = Host.HostAllocationState.Enabled; + this.storageUrl = url; } public void setPodId(Long podId) { @@ -671,16 +673,6 @@ public class HostVO implements Host { return hypervisorType; } - @Override - public HostAllocationState getHostAllocationState() { - return hostAllocationState; - } - - public void setHostAllocationState(HostAllocationState hostAllocationState) { - this.hostAllocationState = hostAllocationState; - } - - public void setHypervisorVersion(String hypervisorVersion) { this.hypervisorVersion = hypervisorVersion; } @@ -688,5 +680,42 @@ public class HostVO implements Host { @Override public String getHypervisorVersion() { return hypervisorVersion; - } + } + + @Override + @Transient + public Status getState() { + return status; + } + + //FIXME: change the upper interface + @Override + public Long getHostId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ResourceState getResourceState() { + return resourceState; + } + + public void setResourceState(ResourceState state) { + resourceState = state; + } + + @Override + public boolean isInMaintenanceStates() { + return (getResourceState() == ResourceState.Maintenance || getResourceState() == ResourceState.ErrorInMaintenance + || getResourceState() == ResourceState.PrepareForMaintenance); + } + + public long getUpdated() { + return updated; + } + + public long incrUpdated() { + updated++; + return updated; + } } diff --git a/core/src/com/cloud/resource/UnableDeleteHostException.java b/core/src/com/cloud/resource/UnableDeleteHostException.java new file mode 100755 index 00000000000..9445cc746df --- /dev/null +++ b/core/src/com/cloud/resource/UnableDeleteHostException.java @@ -0,0 +1,11 @@ +package com.cloud.resource; + +import com.cloud.utils.SerialVersionUID; + +public class UnableDeleteHostException extends Exception { + private static final long serialVersionUID = SerialVersionUID.UnableDeleteHostException; + + public UnableDeleteHostException(String msg) { + super(msg); + } +} diff --git a/ovm/src/com/cloud/ovm/hypervisor/OvmDiscoverer.java b/ovm/src/com/cloud/ovm/hypervisor/OvmDiscoverer.java index 23b259a788f..6aa39b98511 100755 --- a/ovm/src/com/cloud/ovm/hypervisor/OvmDiscoverer.java +++ b/ovm/src/com/cloud/ovm/hypervisor/OvmDiscoverer.java @@ -15,6 +15,8 @@ import org.apache.log4j.Logger; import org.apache.xmlrpc.XmlRpcException; import com.cloud.configuration.Config; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.exception.DiscoveryException; @@ -25,19 +27,23 @@ import com.cloud.ovm.object.Connection; import com.cloud.ovm.object.OvmHost; import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.utils.component.Inject; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.ssh.SSHCmdHelper; @Local(value=Discoverer.class) -public class OvmDiscoverer extends DiscovererBase implements Discoverer { +public class OvmDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(OvmDiscoverer.class); protected String _publicNetworkDevice; protected String _privateNetworkDevice; protected String _guestNetworkDevice; @Inject ClusterDao _clusterDao; + @Inject ResourceManager _resourceMgr; @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -51,6 +57,18 @@ public class OvmDiscoverer extends DiscovererBase implements Discoverer { protected OvmDiscoverer() { } + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); + return super.configure(name, params); + } + + @Override + public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); + return super.stop(); + } + @Override public Map> find(long dcId, Long podId, Long clusterId, URI url, String username, @@ -184,4 +202,32 @@ public class OvmDiscoverer extends DiscovererBase implements Discoverer { return HypervisorType.Ovm; } + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupRoutingCommand)) { + return null; + } + + StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd); + if (ssCmd.getHypervisorType() != HypervisorType.Ovm) { + return null; + } + + return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.Ovm, details, hostTags); + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } + } diff --git a/server/.classpath b/server/.classpath old mode 100644 new mode 100755 index 77a010dd9da..0d7bf4f4617 --- a/server/.classpath +++ b/server/.classpath @@ -1,14 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/server/src/com/cloud/agent/AgentManager.java b/server/src/com/cloud/agent/AgentManager.java index 838c9b56174..88d5b70544f 100755 --- a/server/src/com/cloud/agent/AgentManager.java +++ b/server/src/com/cloud/agent/AgentManager.java @@ -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. * @@ -156,26 +164,6 @@ public interface AgentManager extends Manager { * @return hosts currently connected. */ Set getConnectedHosts(); - - /** - * Disconnect the agent. - * - * @param hostId - * host to disconnect. - * @param reason - * the reason why we're disconnecting. - * - */ - void disconnect(long hostId, Status.Event event, boolean investigate); - - /** - * Obtains statistics for a host; vCPU utilisation, memory utilisation, and network utilisation - * - * @param hostId - * @return HostStat - */ - - boolean disconnect(long hostId); HostStats getHostStatistics(long hostId); @@ -187,29 +175,6 @@ public interface AgentManager extends Manager { List 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 hostDetails); - - /** - * Deletes a host - * - * @param hostId - * @param isForced - * TODO - * @param caller - * TODO - * @param true if deleted, false otherwise - */ - boolean deleteHost(long hostId, boolean isForced, boolean forceDestroy, User caller); - /** * Find a pod based on the user id, template, and data center. * @@ -220,46 +185,38 @@ public interface AgentManager extends Manager { */ Pair findPod(VirtualMachineTemplate template, ServiceOfferingVO offering, DataCenterVO dc, long userId, Set avoids); - /** - * Put the agent in maintenance mode. - * - * @param hostId - * id of the host to put in maintenance mode. - * @return true if it was able to put the agent into maintenance mode. false if not. - */ - boolean maintain(long hostId) throws AgentUnavailableException; - - boolean maintenanceFailed(long hostId); - - /** - * Cancel the maintenance mode. - * - * @param hostId - * host id - * @return true if it's done. false if not. - */ - boolean cancelMaintenance(long hostId); - public boolean executeUserRequest(long hostId, Event event) throws AgentUnavailableException; - public boolean reconnect(final long hostId) throws AgentUnavailableException; - boolean isHostNativeHAEnabled(long hostId); Answer sendTo(Long dcId, HypervisorType type, Command cmd); void notifyAnswersToMonitors(long agentId, long seq, Answer[] answers); - AgentAttache simulateStart(Long id, ServerResource resource, Map details, boolean old, List hostTags, String allocationState, boolean forRebalance) throws IllegalArgumentException; - - boolean updateHostPassword(UpdateHostPasswordCmd upasscmd); - long sendToSecStorage(HostVO ssHost, Command cmd, Listener listener); Answer sendToSecStorage(HostVO ssHost, Command cmd); HostVO getSSAgent(HostVO ssHost); + + /* working as a lock while agent is being loaded */ + public boolean tapLoadingAgents(Long hostId, TapAgentsAction action); + + public AgentAttache handleDirectConnectAgent(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance) throws ConnectionException; + + public boolean agentStatusTransitTo(HostVO host, Status.Event e, long msId); + + public AgentAttache findAttache(long hostId); + + void disconnectWithoutInvestigation(long hostId, Status.Event event); + + void disconnectWithInvestigation(long hostId, Status.Event event); + + public boolean disconnectAgent(HostVO host, Status.Event e, long msId); + + public void pullAgentToMaintenance(long hostId); + + public void pullAgentOutMaintenance(long hostId); - void updateStatus(HostVO host, Event event); - + boolean reconnect(long hostId); } diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index a2fecad3d84..9541cc5ddd0 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -21,6 +21,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.nio.channels.ClosedChannelException; import java.util.ArrayList; +import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -104,7 +105,6 @@ import com.cloud.ha.HighAvailabilityManager; import com.cloud.ha.HighAvailabilityManager.WorkType; import com.cloud.host.DetailVO; import com.cloud.host.Host; -import com.cloud.host.Host.HostAllocationState; import com.cloud.host.Host.Type; import com.cloud.host.HostStats; import com.cloud.host.HostVO; @@ -118,6 +118,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; @@ -131,6 +133,7 @@ import com.cloud.storage.dao.StoragePoolDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.resource.DummySecondaryStorageResource; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.AccountManager; import com.cloud.user.User; @@ -148,6 +151,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; @@ -179,6 +184,7 @@ import edu.emory.mathcs.backport.java.util.Collections; @Local(value = { AgentManager.class }) public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { private static final Logger s_logger = Logger.getLogger(AgentManagerImpl.class); + private static final Logger status_logger = Logger.getLogger(Status.class); protected ConcurrentHashMap _agents = new ConcurrentHashMap(10007); protected List> _hostMonitors = new ArrayList>(17); @@ -241,7 +247,8 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { @Inject protected HypervisorGuruManager _hvGuruMgr; - + + @Inject SecondaryStorageVmManager _ssvmMgr; protected int _retry = 2; @@ -260,6 +267,10 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { protected AgentMonitor _monitor = null; protected ExecutorService _executor; + + protected StateMachine2 _statusStateMachine = Status.getStateMachine(); + + @Inject ResourceManager _resourceMgr; @Override public boolean configure(final String name, final Map params) throws ConfigurationException { @@ -412,6 +423,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { } } + @Override public AgentAttache findAttache(long hostId) { AgentAttache attache = null; synchronized (_agents) { @@ -469,32 +481,6 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { return pcs; } - protected AgentAttache handleDirectConnect(ServerResource resource, StartupCommand[] startup, Map details, boolean old, List hostTags, String allocationState, boolean forRebalance) - throws ConnectionException { - - if (startup == null) { - return null; - } - HostVO server = createHost(startup, resource, details, old, hostTags, allocationState); - if (server == null) { - return null; - } - - long id = server.getId(); - - AgentAttache attache = createAttache(id, server, resource); - StartupAnswer[] answers = new StartupAnswer[startup.length]; - for (int i = 0; i < answers.length; i++) { - answers[i] = new StartupAnswer(startup[i], attache.getId(), _pingInterval); - } - - attache.process(answers); - - attache = notifyMonitorsOfConnection(attache, startup, forRebalance); - - return attache; - } - @Override public Answer sendToSecStorage(HostVO ssHost, Command cmd) { if( ssHost.getType() == Host.Type.LocalSecondaryStorage ) { @@ -515,7 +501,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { return ssHost; } else if ( ssHost.getType() == Host.Type.SecondaryStorage) { Long dcId = ssHost.getDataCenterId(); - List ssAHosts = _hostDao.listSecondaryStorageVM(dcId); + List ssAHosts = _ssvmMgr.listUpSecondaryStorageVmHost(dcId); if (ssAHosts == null || ssAHosts.isEmpty() ) { return null; } @@ -541,7 +527,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { private long sendToSSVM(final long dcId, final Command cmd, final Listener listener) { - List ssAHosts = _hostDao.listSecondaryStorageVM(dcId); + List ssAHosts = _ssvmMgr.listUpSecondaryStorageVmHost(dcId); if (ssAHosts == null || ssAHosts.isEmpty() ) { return -1; } @@ -555,7 +541,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { } private Answer sendToSSVM(final long dcId, final Command cmd) { - List ssAHosts = _hostDao.listSecondaryStorageVM(dcId); + List ssAHosts = _ssvmMgr.listUpSecondaryStorageVmHost(dcId); if (ssAHosts == null || ssAHosts.isEmpty() ) { return new Answer(cmd, false, "can not find secondary storage VM agent for data center " + dcId); } @@ -569,7 +555,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { List clusters = _clusterDao.listByDcHyType(dcId, type.toString()); int retry = 0; for (ClusterVO cluster : clusters) { - List hosts = _hostDao.listBy(Host.Type.Routing, cluster.getId(), null, dcId); + List hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), null, dcId); for (HostVO host : hosts) { retry++; if (retry > _retry) { @@ -590,213 +576,6 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { return null; } - @Override - @DB - public boolean deleteHost(long hostId, boolean isForced, boolean forceDestroy, User caller) { - - // Check if the host exists - HostVO host = _hostDao.findById(hostId); - if (host == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Host: " + hostId + " does not even exist. Delete call is ignored."); - } - return true; - } - - AgentAttache attache = findAttache(hostId); - // Get storage pool host mappings here because they can be removed as a part of handleDisconnect later - List pools = _storagePoolHostDao.listByHostIdIncludingRemoved(hostId); - - try { - - if (host.getType() == Type.Routing) { - // Check if host is ready for removal - Status currentState = host.getStatus(); - Status nextState = currentState.getNextStatus(Status.Event.Remove); - if (nextState == null) { - s_logger.debug("There is no transition from state " + currentState + " to state " + Status.Event.Remove); - return false; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Deleting Host: " + hostId + " Guid:" + host.getGuid()); - } - - if (forceDestroy) { - //put local storage into mainenance mode, will set all the VMs on this local storage into stopped state - StoragePool storagePool = _storageMgr.findLocalStorageOnHost(host.getId()); - if (storagePool != null) { - if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) { - try { - storagePool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId()); - if (storagePool == null) { - s_logger.debug("Failed to set primary storage into maintenance mode"); - return false; - } - } catch (Exception e) { - s_logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString()); - return false; - } - } - List vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId()); - for (VMInstanceVO vm : vmsOnLocalStorage) { - if(!_vmMgr.destroy(vm, caller, _accountMgr.getAccount(vm.getAccountId()))) { - String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + hostId; - s_logger.warn(errorMsg); - throw new CloudRuntimeException(errorMsg); - } - } - } - } else { - // Check if there are vms running/starting/stopping on this host - List vms = _vmDao.listByHostId(hostId); - if (!vms.isEmpty()) { - if (isForced) { - // Stop HA disabled vms and HA enabled vms in Stopping state - // Restart HA enabled vms - for (VMInstanceVO vm : vms) { - if (!vm.isHaEnabled() || vm.getState() == State.Stopping) { - s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + hostId); - if (!_vmMgr.advanceStop(vm, true, caller, _accountMgr.getAccount(vm.getAccountId()))) { - String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + hostId; - s_logger.warn(errorMsg); - throw new CloudRuntimeException(errorMsg); - } - } else if (vm.isHaEnabled() && (vm.getState() == State.Running || vm.getState() == State.Starting)) { - s_logger.debug("Scheduling restart for vm: " + vm + " " + vm.getState() + " on the host id=" + hostId); - _haMgr.scheduleRestart(vm, false); - } - } - } else { - throw new CloudRuntimeException("Unable to delete the host as there are vms in " + vms.get(0).getState() + " state using this host and isForced=false specified"); - } - } - } - - if (host.getHypervisorType() == HypervisorType.XenServer) { - if (host.getClusterId() != null) { - List hosts = _hostDao.listBy(Type.Routing, host.getClusterId(), host.getPodId(), host.getDataCenterId()); - hosts.add(host); - boolean success = true; - for (HostVO thost : hosts) { - long thostId = thost.getId(); - PoolEjectCommand eject = new PoolEjectCommand(host.getGuid()); - Answer answer = easySend(thostId, eject); - if (answer != null && answer.getResult()) { - s_logger.debug("Eject Host: " + hostId + " from " + thostId + " Succeed"); - success = true; - break; - } else { - success = false; - s_logger.warn("Eject Host: " + hostId + " from " + thostId + " failed due to " + (answer != null ? answer.getDetails() : "no answer")); - } - } - if (!success) { - String msg = "Unable to eject host " + host.getGuid() + " due to there is no host up in this cluster, please execute xe pool-eject host-uuid=" + host.getGuid() - + "in this host " + host.getPrivateIpAddress(); - s_logger.warn(msg); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Unable to eject host " + host.getGuid(), msg); - } - } - } else if (host.getHypervisorType() == HypervisorType.KVM) { - try { - ShutdownCommand cmd = new ShutdownCommand(ShutdownCommand.DeleteHost, null); - send(host.getId(), cmd); - } catch (AgentUnavailableException e) { - s_logger.warn("Sending ShutdownCommand failed: ", e); - } catch (OperationTimedoutException e) { - s_logger.warn("Sending ShutdownCommand failed: ", e); - } - } else if (host.getHypervisorType() == HypervisorType.BareMetal) { - List deadVms = _vmDao.listByLastHostId(hostId); - for (VMInstanceVO vm : deadVms) { - if (vm.getState() == State.Running || vm.getHostId() != null) { - throw new CloudRuntimeException("VM " + vm.getId() + "is still running on host " + hostId); - } - _vmDao.remove(vm.getId()); - } - } - } - - Transaction txn = Transaction.currentTxn(); - txn.start(); - - _dcDao.releasePrivateIpAddress(host.getPrivateIpAddress(), host.getDataCenterId(), null); - if (attache != null) { - handleDisconnect(attache, Status.Event.Remove, false); - } - // delete host details - _hostDetailsDao.deleteDetails(hostId); - - host.setGuid(null); - Long clusterId = host.getClusterId(); - host.setClusterId(null); - _hostDao.update(host.getId(), host); - - _hostDao.remove(hostId); - if (clusterId != null) { - List hosts = _hostDao.listByCluster(clusterId); - if (hosts.size() == 0) { - ClusterVO cluster = _clusterDao.findById(clusterId); - cluster.setGuid(null); - _clusterDao.update(clusterId, cluster); - } - } - - // Delete the associated entries in host ref table - _storagePoolHostDao.deletePrimaryRecordsForHost(hostId); - - // For pool ids you got, delete local storage host entries in pool table where - for (StoragePoolHostVO pool : pools) { - Long poolId = pool.getPoolId(); - StoragePoolVO storagePool = _storagePoolDao.findById(poolId); - if (storagePool.isLocal() && forceDestroy) { - storagePool.setUuid(null); - storagePool.setClusterId(null); - _storagePoolDao.update(poolId, storagePool); - _storagePoolDao.remove(poolId); - _capacityDao.removeBy(Capacity.CAPACITY_TYPE_LOCAL_STORAGE, null, null, null, poolId); - s_logger.debug("Local storage id=" + poolId + " is removed as a part of host removal id=" + hostId); - } - } - - //Delete op_host_capacity entries - _capacityDao.removeBy(Capacity.CAPACITY_TYPE_MEMORY, null, null, null, hostId); - _capacityDao.removeBy(Capacity.CAPACITY_TYPE_CPU, null, null, null, hostId); - txn.commit(); - return true; - } catch (Throwable t) { - s_logger.error("Unable to delete host: " + hostId, t); - return false; - } - } - - @Override - public boolean updateHostPassword(UpdateHostPasswordCmd upasscmd) { - if (upasscmd.getClusterId() == null) { - //update agent attache password - AgentAttache agent = this.findAttache(upasscmd.getHostId()); - if (!(agent instanceof DirectAgentAttache)) { - return false; - } - UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(upasscmd.getUsername(), upasscmd.getPassword()); - agent.updatePassword(cmd); - } - else { - // get agents for the cluster - List hosts = _hostDao.listByCluster(upasscmd.getClusterId()); - for (HostVO h : hosts) { - AgentAttache agent = this.findAttache(h.getId()); - if (!(agent instanceof DirectAgentAttache)) { - continue; - } - UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(upasscmd.getUsername(), upasscmd.getPassword()); - agent.updatePassword(cmd); - } - } - return true; - } - protected int getPingInterval() { return _pingInterval; } @@ -946,174 +725,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { removed.disconnect(nextState); } } - - @Override - public void disconnect(final long hostId, final Status.Event event, final boolean investigate) { - AgentAttache attache = findAttache(hostId); - - if (attache != null) { - disconnect(attache, event, investigate); - } else { - synchronized (_loadingAgents) { - if (_loadingAgents.contains(hostId)) { - s_logger.info("Host " + hostId + " is being loaded so no disconnects needed."); - return; - } - } - - HostVO host = _hostDao.findById(hostId); - if (host != null && host.getRemoved() == null) { - if (event != null && event.equals(Event.Remove)) { - host.setGuid(null); - host.setClusterId(null); - } - _hostDao.updateStatus(host, event, _nodeId); - } - } - } - @Override - public boolean disconnect(final long hostId) { - disconnect(hostId, Event.PrepareUnmanaged, false); - return true; - } - - @Override - public void updateStatus(HostVO host, Status.Event event) { - _hostDao.updateStatus(host, event, _nodeId); - } - public void disconnect(AgentAttache attache, final Status.Event event, final boolean investigate) { - _executor.submit(new DisconnectTask(attache, event, investigate)); - } - - protected boolean handleDisconnect(AgentAttache attache, Status.Event event, boolean investigate) { - if (attache == null) { - return true; - } - - long hostId = attache.getId(); - - s_logger.info("Host " + hostId + " is disconnecting with event " + event); - - HostVO host = _hostDao.findById(hostId); - if (host == null) { - s_logger.warn("Can't find host with " + hostId); - removeAgent(attache, Status.Removed); - return true; - - } - final Status currentState = host.getStatus(); - if (currentState == Status.Down || currentState == Status.Alert || currentState == Status.Removed) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Host " + hostId + " is already " + currentState); - } - if (currentState != Status.PrepareForMaintenance) { - removeAgent(attache, currentState); - } - return true; - } - Status nextState = currentState.getNextStatus(event); - if (nextState == null) { - if (!(attache instanceof DirectAgentAttache)) { - return false; - } - - s_logger.debug("There is no transition from state " + currentState + " and event " + event); - assert false : "How did we get here. Look at the FSM"; - return false; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("The next state is " + nextState + ", current state is " + currentState); - } - - // Now we go and correctly diagnose what the actual situation is - if (nextState == Status.Alert && investigate) { - s_logger.info("Investigating why host " + hostId + " has disconnected with event " + event); - - final Status determinedState = investigate(attache); - s_logger.info("The state determined is " + determinedState); - - if (determinedState == null || determinedState == Status.Down) { - s_logger.error("Host is down: " + host.getId() + "-" + host.getName() + ". Starting HA on the VMs"); - - event = Event.HostDown; - } else if (determinedState == Status.Up) { - // we effectively pinged from the server here. - s_logger.info("Agent is determined to be up and running"); - _monitor.pingBy(host.getId()); - // _hostDao.updateStatus(host, Event.Ping, _nodeId); - return false; - } else if (determinedState == Status.Disconnected) { - s_logger.warn("Agent is disconnected but the host is still up: " + host.getId() + "-" + host.getName()); - if (currentState == Status.Disconnected) { - Long hostPingTime = _monitor.getAgentPingTime(host.getId()); - if (hostPingTime == null) { - s_logger.error("Host is not on this management server any more: " + host); - return false; - } - if ((InaccurateClock.getTimeInSeconds() - hostPingTime) > _alertWait) { - s_logger.warn("Host " + host.getId() + " has been disconnected pass the time it should be disconnected."); - event = Event.WaitedTooLong; - } else { - s_logger.debug("Host has been determined to be disconnected but it hasn't passed the wait time yet."); - return false; - } - } else if (currentState == Status.Updating) { - Long hostPingTime = _monitor.getAgentPingTime(host.getId()); - if (hostPingTime == null) { - s_logger.error("Host is not on this management server any more: " + host); - return false; - } - if ((InaccurateClock.getTimeInSeconds() - hostPingTime) > _updateWait) { - s_logger.warn("Host " + host.getId() + " has been updating for too long"); - - event = Event.WaitedTooLong; - } else { - s_logger.debug("Host has been determined to be disconnected but it hasn't passed the wait time yet."); - return false; - } - } else if (currentState == Status.Up) { - DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId()); - HostPodVO podVO = _podDao.findById(host.getPodId()); - String hostDesc = "name: " + host.getName() + " (id:" + host.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName(); - if ((host.getType() != Host.Type.SecondaryStorage) && (host.getType() != Host.Type.ConsoleProxy)) { - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Host disconnected, " + hostDesc, "If the agent for host [" + hostDesc - + "] is not restarted within " + _alertWait + " seconds, HA will begin on the VMs"); - } - event = Event.AgentDisconnected; - } - } else { - // if we end up here we are in alert state, send an alert - DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId()); - HostPodVO podVO = _podDao.findById(host.getPodId()); - String hostDesc = "name: " + host.getName() + " (id:" + host.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName(); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Host in ALERT state, " + hostDesc, "In availability zone " + host.getDataCenterId() - + ", host is in alert state: " + host.getId() + "-" + host.getName()); - } - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Deregistering link for " + hostId + " with state " + nextState); - } - removeAgent(attache, nextState); - _hostDao.disconnect(host, event, _nodeId); - - host = _hostDao.findById(host.getId()); - if (!event.equals(Event.PrepareUnmanaged) && !event.equals(Event.HypervisorVersionChanged) && (host.getStatus() == Status.Alert || host.getStatus() == Status.Down)) { - _haMgr.scheduleRestartForVmsOnHost(host, investigate); - } - - for (Pair monitor : _hostMonitors) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Sending Disconnect to listener: " + monitor.second().getClass().getName()); - } - monitor.second().processDisconnect(hostId, nextState); - } - - return true; - } - protected AgentAttache notifyMonitorsOfConnection(AgentAttache attache, final StartupCommand[] cmd, boolean forRebalance) throws ConnectionException { long hostId = attache.getId(); HostVO host = _hostDao.findById(hostId); @@ -1129,19 +741,19 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { ConnectionException ce = (ConnectionException)e; if (ce.isSetupError()) { s_logger.warn("Monitor " + monitor.second().getClass().getSimpleName() + " says there is an error in the connect process for " + hostId + " due to " + e.getMessage()); - handleDisconnect(attache, Event.AgentDisconnected, false); + handleDisconnectWithoutInvestigation(attache, Event.AgentDisconnected); throw ce; } else { s_logger.info("Monitor " + monitor.second().getClass().getSimpleName() + " says not to continue the connect process for " + hostId + " due to " + e.getMessage()); - handleDisconnect(attache, Event.ShutdownRequested, false); + handleDisconnectWithoutInvestigation(attache, Event.ShutdownRequested); return attache; } } else if (e instanceof HypervisorVersionChangedException) { - handleDisconnect(attache, Event.HypervisorVersionChanged, false); + handleDisconnectWithoutInvestigation(attache, Event.ShutdownRequested); throw new CloudRuntimeException("Unable to connect " + attache.getId(), e); } else { s_logger.error("Monitor " + monitor.second().getClass().getSimpleName() + " says there is an error in the connect process for " + hostId + " due to " + e.getMessage(), e); - handleDisconnect(attache, Event.AgentDisconnected, false); + handleDisconnectWithoutInvestigation(attache, Event.AgentDisconnected); throw new CloudRuntimeException("Unable to connect " + attache.getId(), e); } } @@ -1155,10 +767,10 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { // this is tricky part for secondary storage // make it as disconnected, wait for secondary storage VM to be up // return the attache instead of null, even it is disconnectede - handleDisconnect(attache, Event.AgentDisconnected, false); + handleDisconnectWithoutInvestigation(attache, Event.AgentDisconnected); } - _hostDao.updateStatus(host, Event.Ready, _nodeId); + agentStatusTransitTo(host, Event.Ready, _nodeId); attache.ready(); return attache; } @@ -1193,7 +805,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { } public void startDirectlyConnectedHosts() { - List hosts = _hostDao.findDirectlyConnectedHosts(); + List hosts = _resourceMgr.findDirectlyConnectedHosts(); for (HostVO host : hosts) { loadDirectlyConnectedHost(host, false); } @@ -1277,88 +889,40 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { } finally { if(!initialized) { if (host != null) { - _hostDao.updateStatus(host, Event.AgentDisconnected, _nodeId); + agentStatusTransitTo(host, Event.AgentDisconnected, _nodeId); } } } 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, true); + return (h == null ? false : true); } else { _executor.execute(new SimulateStartTask(host.getId(), resource, host.getDetails(), null)); return true; } } - @Override - public AgentAttache simulateStart(Long id, ServerResource resource, Map details, boolean old, List 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); - } + protected AgentAttache createAttacheForDirectConnect(HostVO host, ServerResource resource) + 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); } + if (old != null) { + old.disconnect(Status.Removed); + } + return attache; } - + @Override public boolean stop() { if (_monitor != null) { @@ -1377,7 +941,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { s_logger.debug("Cant not find host " + agent.getId()); } } else { - _hostDao.updateStatus(host, Event.ManagementServerDown, _nodeId); + agentStatusTransitTo(host, Event.ManagementServerDown, _nodeId); } } } @@ -1449,6 +1013,126 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { public String getName() { return _name; } + + protected boolean handleDisconnectWithoutInvestigation(AgentAttache attache, Status.Event event) { + long hostId = attache.getId(); + + s_logger.info("Host " + hostId + " is disconnecting with event " + event); + Status nextStatus = null; + HostVO host = _hostDao.findById(hostId); + if (host == null) { + s_logger.warn("Can't find host with " + hostId); + nextStatus = Status.Removed; + } else { + final Status currentStatus = host.getStatus(); + if (currentStatus == Status.Down || currentStatus == Status.Alert || currentStatus == Status.Removed) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Host " + hostId + " is already " + currentStatus); + } + nextStatus = currentStatus; + } else { + try { + nextStatus = currentStatus.getNextStatus(event); + } catch (NoTransitionException e) { + String err = "Cannot find next status for " + event + " as current status is " + currentStatus + " for agent " + hostId; + s_logger.debug(err); + throw new CloudRuntimeException(err); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("The next status of agent " + hostId + "is " + nextStatus + ", current status is " + currentStatus); + } + } + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Deregistering link for " + hostId + " with state " + nextStatus); + } + + removeAgent(attache, nextStatus); + disconnectAgent(host, event, _nodeId); + + for (Pair monitor : _hostMonitors) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Sending Disconnect to listener: " + monitor.second().getClass().getName()); + } + monitor.second().processDisconnect(hostId, nextStatus); + } + return true; + } + + protected boolean handleDisconnectWithInvestigation(AgentAttache attache, Status.Event event) { + long hostId = attache.getId(); + HostVO host = _hostDao.findById(hostId); + if (host != null) { + Status nextStatus = null; + try { + nextStatus = host.getStatus().getNextStatus(event); + } catch (NoTransitionException ne) { + /* Agent may be currently in status of Down, Alert, Removed, namely there is no next status for some events. + * Why this can happen? Ask God not me. I hate there was no piece of comment for code handling race condition. + * God knew what race condition the code dealt with! + */ + } + + if (nextStatus == Status.Alert) { + /* OK, we are going to the bad status, let's see what happened */ + s_logger.info("Investigating why host " + hostId + " has disconnected with event " + event); + + final Status determinedState = investigate(attache); + final Status currentStatus = host.getStatus(); + s_logger.info("The state determined is " + determinedState); + + if (determinedState == null || determinedState == Status.Down) { + s_logger.error("Host is down: " + host.getId() + "-" + host.getName() + ". Starting HA on the VMs"); + event = Status.Event.HostDown; + } else if (determinedState == Status.Up) { + /* Got ping response from host, bring it back*/ + s_logger.info("Agent is determined to be up and running"); + agentStatusTransitTo(host, Status.Event.Ping, _nodeId); + return false; + } else if (determinedState == Status.Disconnected) { + s_logger.warn("Agent is disconnected but the host is still up: " + host.getId() + "-" + host.getName()); + if (currentStatus == Status.Disconnected) { + if (((System.currentTimeMillis() >> 10) - host.getLastPinged()) > _alertWait) { + s_logger.warn("Host " + host.getId() + " has been disconnected pass the time it should be disconnected."); + event = Status.Event.WaitedTooLong; + } else { + s_logger.debug("Host has been determined to be disconnected but it hasn't passed the wait time yet."); + return false; + } + } else if (currentStatus == Status.Up) { + DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId()); + HostPodVO podVO = _podDao.findById(host.getPodId()); + String hostDesc = "name: " + host.getName() + " (id:" + host.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName(); + if ((host.getType() != Host.Type.SecondaryStorage) && (host.getType() != Host.Type.ConsoleProxy)) { + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Host disconnected, " + hostDesc, "If the agent for host [" + hostDesc + + "] is not restarted within " + _alertWait + " seconds, HA will begin on the VMs"); + } + event = Status.Event.AgentDisconnected; + } + } else { + // if we end up here we are in alert state, send an alert + DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId()); + HostPodVO podVO = _podDao.findById(host.getPodId()); + String hostDesc = "name: " + host.getName() + " (id:" + host.getId() + "), availability zone: " + dcVO.getName() + ", pod: " + podVO.getName(); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Host in ALERT state, " + hostDesc, "In availability zone " + host.getDataCenterId() + + ", host is in alert state: " + host.getId() + "-" + host.getName()); + } + } else { + s_logger.debug("The next status of Agent " + host.getId() + " is not Alert, no need to investigate what happened"); + } + } + + handleDisconnectWithoutInvestigation(attache, event); + /*TODO: call HA manager in monitors + * host = _hostDao.findById(host.getId()); + if (!event.equals(Event.PrepareUnmanaged) && !event.equals(Event.HypervisorVersionChanged) && (host.getStatus() == Status.Alert || host.getStatus() == Status.Down)) { + _haMgr.scheduleRestartForVmsOnHost(host, investigate); + } + * */ + return true; + } protected class DisconnectTask implements Runnable { AgentAttache _attache; @@ -1463,8 +1147,12 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { @Override public void run() { - try { - handleDisconnect(_attache, _event, _investigate); + try { + if (_investigate == true) { + handleDisconnectWithInvestigation(_attache, _event); + } else { + handleDisconnectWithoutInvestigation(_attache, _event); + } } catch (final Exception e) { s_logger.error("Exception caught while handling disconnect: ", e); } finally { @@ -1521,7 +1209,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { } @Override - public boolean reconnect(final long hostId) throws AgentUnavailableException { + public boolean reconnect(final long hostId) { HostVO host; host = _hostDao.findById(hostId); @@ -1541,627 +1229,57 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { return false; } - disconnect(attache, Event.ShutdownRequested, false); - return true; - } - - @Override - public boolean cancelMaintenance(final long hostId) { - - HostVO host; - host = _hostDao.findById(hostId); - if (host == null || host.getRemoved() != null) { - s_logger.warn("Unable to find host " + hostId); - return true; - } - - if (host.getStatus() != Status.PrepareForMaintenance && host.getStatus() != Status.Maintenance && host.getStatus() != Status.ErrorInMaintenance) { - return true; - } - - _haMgr.cancelScheduledMigrations(host); - List vms = _haMgr.findTakenMigrationWork(); - for (VMInstanceVO vm : vms) { - if (vm.getHostId() != null && vm.getHostId() == hostId) { - s_logger.info("Unable to cancel migration because the vm is being migrated: " + vm); - return false; - } - } - disconnect(hostId, Event.ResetRequested, false); + disconnectWithoutInvestigation(attache, Event.ShutdownRequested); return true; } @Override public boolean executeUserRequest(long hostId, Event event) throws AgentUnavailableException { - if (event == Event.MaintenanceRequested) { - return maintain(hostId); - } else if (event == Event.ResetRequested) { - return cancelMaintenance(hostId); - } else if (event == Event.PrepareUnmanaged) { - return disconnect(hostId); - } else if (event == Event.Remove) { - User caller = _accountMgr.getActiveUser(User.UID_SYSTEM); - return deleteHost(hostId, false, false, caller); - } else if (event == Event.AgentDisconnected) { + if (event == Event.AgentDisconnected) { if (s_logger.isDebugEnabled()) { s_logger.debug("Received agent disconnect event for host " + hostId); } AgentAttache attache = null; attache = findAttache(hostId); if (attache != null) { - handleDisconnect(attache, Event.AgentDisconnected, false); + handleDisconnectWithoutInvestigation(attache, Event.AgentDisconnected); } return true; } else if (event == Event.ShutdownRequested) { return reconnect(hostId); } - else if (event == Event.UpdatePassword) { - AgentAttache attache = findAttache(hostId); - if (attache != null) { - DetailVO nv = _detailsDao.findDetail(hostId, ApiConstants.USERNAME); - String username = nv.getValue(); - nv = _detailsDao.findDetail(hostId, ApiConstants.PASSWORD); - String password = nv.getValue(); - UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(username, password); - attache.updatePassword(cmd); - return true; - } - } return false; } - @Override - public boolean maintain(final long hostId) throws AgentUnavailableException { - HostVO host = _hostDao.findById(hostId); - Status state; - - MaintainAnswer answer = (MaintainAnswer) easySend(hostId, new MaintainCommand()); - if (answer == null || !answer.getResult()) { - s_logger.warn("Unable to put host in maintainance mode: " + hostId); - return false; - } - - // Let's put this guy in maintenance state - do { - host = _hostDao.findById(hostId); - if (host == null) { - s_logger.debug("Unable to find host " + hostId); - return false; - } - state = host.getStatus(); - if (state == Status.Disconnected || state == Status.Updating) { - s_logger.debug("Unable to put host " + hostId + " in matinenance mode because it is currently in " + state); - throw new AgentUnavailableException("Agent is in " + state + " state. Please wait for it to become Alert state try again.", hostId); - } - } while (!_hostDao.updateStatus(host, Event.MaintenanceRequested, _nodeId)); - - AgentAttache attache = findAttache(hostId); - if (attache != null) { - attache.setMaintenanceMode(true); - } - - if (attache != null) { - // Now cancel all of the commands except for the active one. - attache.cancelAllCommands(Status.PrepareForMaintenance, false); - } - - final Host.Type type = host.getType(); - - if (type == 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()); - List upHosts = _hostDao.listBy( host.getDataCenterId(), host.getPodId(), host.getClusterId(), Host.Type.Routing, Status.Up); - for (final VMInstanceVO vm : vms) { - if (hosts == null || hosts.size() <= 1 || !answer.getMigrate() || upHosts == null || upHosts.size() == 0) { - // for the last valid host in this cluster, stop all the VMs - _haMgr.scheduleStop(vm, hostId, WorkType.ForceStop); - } else { - _haMgr.scheduleMigration(vm); - } - } - } - - return true; - } - - - public boolean checkCIDR(Host.Type type, 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 void checkCIDR(Host.Type type, HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask) throws IllegalArgumentException { - // Skip this check for Storage Agents and Console Proxies - if (type == Host.Type.Storage || type == Host.Type.ConsoleProxy) { - return; - } - - if (serverPrivateIP == null) { - return; - } - // 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)) { - s_logger.warn("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName() + " and zone: " + dc.getName()); - throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName() + " and zone: " + dc.getName()); - } - - // 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) { - throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName() + " and zone: " + dc.getName()); - } - - } - - public void checkIPConflicts(Host.Type type, HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask, String serverPublicIP, String serverPublicNetmask) { - // If the server's private IP is the same as is public IP, this host has - // a host-only private network. Don't check for conflicts with the - // private IP address table. - if (serverPrivateIP != serverPublicIP) { - if (!_privateIPAddressDao.mark(dc.getId(), pod.getId(), serverPrivateIP)) { - // If the server's private IP address is already in the - // database, return false - List existingPrivateIPs = _privateIPAddressDao.listByPodIdDcIdIpAddress(pod.getId(), dc.getId(), serverPrivateIP); - - assert existingPrivateIPs.size() <= 1 : " How can we get more than one ip address with " + serverPrivateIP; - if (existingPrivateIPs.size() > 1) { - throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is already in use in pod: " + pod.getName() + " and zone: " + dc.getName()); - } - if (existingPrivateIPs.size() == 1) { - DataCenterIpAddressVO vo = existingPrivateIPs.get(0); - if (vo.getInstanceId() != null) { - throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is already in use in pod: " + pod.getName() + " and zone: " + dc.getName()); - } - } - } - } - - if (serverPublicIP != null && !_publicIPAddressDao.mark(dc.getId(), new Ip(serverPublicIP))) { - // If the server's public IP address is already in the database, - // return false - List existingPublicIPs = _publicIPAddressDao.listByDcIdIpAddress(dc.getId(), serverPublicIP); - if (existingPublicIPs.size() > 0) { - throw new IllegalArgumentException("The public ip address of the server (" + serverPublicIP + ") is already in use in zone: " + dc.getName()); - } - } - } - - @Override - public Host addHost(long zoneId, ServerResource resource, Type hostType, Map 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 details = hostDetails; - String guid = details.get("guid"); - List 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 details, boolean directFirst, List hostTags, String allocationState) - throws IllegalArgumentException { - Host.Type type = null; - - if (startup instanceof StartupStorageCommand) { - StartupStorageCommand ssCmd = ((StartupStorageCommand) startup); - if (ssCmd.getHostType() == Host.Type.SecondaryStorageCmdExecutor) { - type = ssCmd.getHostType(); - } else { - if (ssCmd.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE) { - type = Host.Type.SecondaryStorage; - if (resource != null && resource instanceof DummySecondaryStorageResource) { - resource = null; - } - }else if (ssCmd.getResourceType() == Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE) { - type = Host.Type.LocalSecondaryStorage; - - } else { - type = Host.Type.Storage; - } - - final Map hostDetails = ssCmd.getHostDetails(); - if (hostDetails != null) { - if (details != null) { - details.putAll(hostDetails); - } else { - details = hostDetails; - } - } - } - } else if (startup instanceof StartupRoutingCommand) { - StartupRoutingCommand ssCmd = ((StartupRoutingCommand) startup); - type = Host.Type.Routing; - final Map hostDetails = ssCmd.getHostDetails(); - if (hostDetails != null) { - if (details != null) { - details.putAll(hostDetails); - } else { - details = hostDetails; - } - } - } else if (startup instanceof StartupSecondaryStorageCommand) { - type = Host.Type.SecondaryStorageVM; - } else if (startup instanceof StartupProxyCommand) { - type = Host.Type.ConsoleProxy; - } else if (startup instanceof StartupExternalFirewallCommand) { - type = Host.Type.ExternalFirewall; - } else if (startup instanceof StartupExternalLoadBalancerCommand) { - type = Host.Type.ExternalLoadBalancer; - } else if (startup instanceof StartupPxeServerCommand) { - type = Host.Type.PxeServer; - } else if (startup instanceof StartupExternalDhcpCommand) { - type = Host.Type.ExternalDhcp; - } else if (startup instanceof StartupTrafficMonitorCommand) { - type = Host.Type.TrafficMonitor; - } else { - assert false : "Did someone add a new Startup command?"; - } - - Long id = null; - HostVO server = _hostDao.findByGuid(startup.getGuid()); - if (server == null) { - server = _hostDao.findByGuid(startup.getGuidWithoutResource()); - } - if (server != null && server.getRemoved() == null) { - id = server.getId(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found the host " + id + " by guid: " + startup.getGuid()); - } - if (directFirst) { - s_logger.debug("Old host reconnected as new"); - return null; - } - } else { - server = new HostVO(startup.getGuid()); - } - - server.setDetails(details); - server.setHostTags(hostTags); - - if (allocationState != null) { - try { - HostAllocationState hostAllocationState = Host.HostAllocationState.valueOf(allocationState); - if (hostAllocationState != null) { - server.setHostAllocationState(hostAllocationState); - } - } catch (IllegalArgumentException ex) { - s_logger.error("Unable to resolve " + allocationState + " to a valid supported host allocation State, defaulting to 'Enabled'"); - server.setHostAllocationState(Host.HostAllocationState.Enabled); - } - } else { - server.setHostAllocationState(Host.HostAllocationState.Enabled); - } - - updateHost(server, startup, type, _nodeId); - if (resource != null) { - server.setResource(resource.getClass().getName()); - } - if (id == null) { - /* - * // ignore integrity check for agent-simulator if(!"0.0.0.0".equals(startup.getPrivateIpAddress()) && - * !"0.0.0.0".equals(startup.getStorageIpAddress())) { if (_hostDao.findByPrivateIpAddressInDataCenter - * (server.getDataCenterId(), startup.getPrivateIpAddress()) != null) { throw newIllegalArgumentException( - * "The private ip address is already in used: " + startup.getPrivateIpAddress()); } - * - * if (_hostDao.findByPrivateIpAddressInDataCenter(server.getDataCenterId (), startup.getStorageIpAddress()) != - * null) { throw new IllegalArgumentException ("The private ip address is already in used: " + - * startup.getStorageIpAddress()); } } - */ - - if (startup instanceof StartupProxyCommand) { - server.setProxyPort(((StartupProxyCommand) startup).getProxyPort()); - } - - server = _hostDao.persist(server); - id = server.getId(); - - s_logger.info("New " + server.getType() + " host connected w/ guid " + startup.getGuid() + " and id is " + id); - } else { - if (!_hostDao.connect(server, _nodeId)) { - throw new CloudRuntimeException("Agent cannot connect because the current state is " + server.getStatus()); - } - s_logger.info("Old " + server.getType() + " host reconnected w/ id =" + id); - } - - return server; - } - - public HostVO createHost(final StartupCommand[] startup, ServerResource resource, Map details, boolean directFirst, List hostTags, String allocationState) - throws IllegalArgumentException { - StartupCommand firstCmd = startup[0]; - HostVO result = createHost(firstCmd, resource, details, directFirst, hostTags, allocationState); - if (result == null) { - return null; - } - return result; - } - - public AgentAttache handleConnect(final Link link, - final StartupCommand[] startup) throws IllegalArgumentException, - ConnectionException { - HostVO server = null; - boolean handled = notifyCreatorsOfConnection(startup); - if (!handled) { - server = createHost(startup, null, null, false, null, null); - } else { - server = _hostDao.findByGuid(startup[0].getGuid()); - } - - if (server == null) { - return null; - } - long id = server.getId(); - - AgentAttache attache = createAttache(id, server, link); - - attache = notifyMonitorsOfConnection(attache, startup, false); - - return attache; - } - - protected AgentAttache createAttache(long id, HostVO server, Link link) { - s_logger.debug("create ConnectedAgentAttache for " + id); - final AgentAttache attache = new ConnectedAgentAttache(this, id, link, server.getStatus() == Status.Maintenance || server.getStatus() == Status.ErrorInMaintenance - || server.getStatus() == Status.PrepareForMaintenance); + protected AgentAttache createAttacheForConnect(HostVO host, Link link) throws ConnectionException { + s_logger.debug("create ConnectedAgentAttache for " + host.getId()); + AgentAttache attache = new ConnectedAgentAttache(this, host.getId(), link, host.isInMaintenanceStates()); link.attach(attache); + AgentAttache old = null; synchronized (_agents) { - old = _agents.put(id, attache); + old = _agents.put(host.getId(), attache); } if (old != null) { old.disconnect(Status.Removed); } + return attache; } - - protected AgentAttache createAttache(long id, HostVO server, ServerResource resource) { - if (resource instanceof DummySecondaryStorageResource || resource instanceof KvmDummyResourceBase) { - return new DummyAttache(this, id, false); - } - s_logger.debug("create DirectAgentAttache for " + id); - final DirectAgentAttache attache = new DirectAgentAttache(this, id, resource, server.getStatus() == Status.Maintenance || server.getStatus() == Status.ErrorInMaintenance - || server.getStatus() == Status.PrepareForMaintenance, this); - AgentAttache old = null; - synchronized (_agents) { - old = _agents.put(id, attache); - } - if (old != null) { - old.disconnect(Status.Removed); + + //TODO: handle mycloud specific + private AgentAttache handleConnectedAgent(final Link link, final StartupCommand[] startup) throws ConnectionException { + AgentAttache attache = null; + HostVO host = _resourceMgr.createHostVOForConnectedAgent(startup); + if (host != null) { + attache = createAttacheForConnect(host, link); } + + attache = notifyMonitorsOfConnection(attache, startup, false); + return attache; } - - @Override - public boolean maintenanceFailed(long hostId) { - HostVO host = _hostDao.findById(hostId); - if (host == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Cant not find host " + hostId); - } - return false; - } else { - return _hostDao.updateStatus(host, Event.UnableToMigrate, _nodeId); - } - } - - - protected void updateHost(final HostVO host, final StartupCommand startup, final Host.Type type, final long msId) throws IllegalArgumentException { - s_logger.debug("updateHost() called"); - - String dataCenter = startup.getDataCenter(); - String pod = startup.getPod(); - String cluster = startup.getCluster(); - - if (pod != null && dataCenter != null && pod.equalsIgnoreCase("default") && dataCenter.equalsIgnoreCase("default")) { - List pods = _podDao.listAllIncludingRemoved(); - for (HostPodVO hpv : pods) { - if (checkCIDR(type, 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) { - } - } - Long podId = null; - if (p == null) { - if (type != Host.Type.SecondaryStorage && type != Host.Type.ExternalFirewall && type != Host.Type.ExternalLoadBalancer && type != Host.Type.TrafficMonitor) { - - /* - * s_logger.info("Unable to find the pod so we are creating one." ); p = createPod(pod, dcId, - * startup.getPrivateIpAddress(), NetUtils.getCidrSize(startup.getPrivateNetmask())); podId = p.getId(); - */ - s_logger.error("Host " + startup.getPrivateIpAddress() + " sent incorrect pod: " + pod + " in " + dataCenter); - throw new IllegalArgumentException("Host " + startup.getPrivateIpAddress() + " sent incorrect pod: " + pod + " in " + dataCenter); - } - } else { - podId = 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(); - } - } - - if (type == Host.Type.Routing) { - StartupRoutingCommand scc = (StartupRoutingCommand) startup; - - HypervisorType hypervisorType = scc.getHypervisorType(); - boolean doCidrCheck = true; - - ClusterVO clusterVO = _clusterDao.findById(clusterId); - if(clusterVO == null){ - throw new IllegalArgumentException("Cluster with id " + clusterId + " does not exist, cannot add host with this clusterId"); - } - if (clusterVO.getHypervisorType() != scc.getHypervisorType()) { - throw new IllegalArgumentException("Can't add host whose hypervisor type is: " + scc.getHypervisorType() + " into cluster: " + clusterId + " whose hypervisor type is: " - + clusterVO.getHypervisorType()); - } - - /* - * KVM:Enforcement that all the hosts in the cluster have the same os type, for migration - */ - if (scc.getHypervisorType() == HypervisorType.KVM) { - List hostsInCluster = _hostDao.listByCluster(clusterId); - if (!hostsInCluster.isEmpty()) { - HostVO oneHost = hostsInCluster.get(0); - _hostDao.loadDetails(oneHost); - String hostOsInCluster = oneHost.getDetail("Host.OS"); - String hostOs = scc.getHostDetails().get("Host.OS"); - if (!hostOsInCluster.equalsIgnoreCase(hostOs)) { - throw new IllegalArgumentException("Can't add host: " + startup.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster," + "in which there are " - + hostOsInCluster + " hosts added"); - } - } - } - - // If this command is from the agent simulator, don't do the CIDR - // check - if (scc.getAgentTag() != null && startup.getAgentTag().equalsIgnoreCase("vmops-simulator")) { - doCidrCheck = false; - } - - // If this command is from a KVM agent, or from an agent that has a - // null hypervisor type, don't do the CIDR check - if (hypervisorType == null || hypervisorType == HypervisorType.KVM || hypervisorType == HypervisorType.VMware || hypervisorType == HypervisorType.BareMetal - || hypervisorType == HypervisorType.Simulator || hypervisorType == HypervisorType.Ovm) { - doCidrCheck = false; - } - - if (doCidrCheck) { - s_logger.info("Host: " + host.getName() + " connected with hypervisor type: " + hypervisorType + ". Checking CIDR..."); - } else { - s_logger.info("Host: " + host.getName() + " connected with hypervisor type: " + hypervisorType + ". Skipping CIDR check..."); - } - - if (doCidrCheck) { - checkCIDR(type, p, dc, scc.getPrivateIpAddress(), scc.getPrivateNetmask()); - } - - // Check if the private/public IPs of the server are already in the - // private/public IP address tables - checkIPConflicts(type, p, dc, scc.getPrivateIpAddress(), scc.getPublicIpAddress(), scc.getPublicIpAddress(), scc.getPublicNetmask()); - } - - 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.setType(type); - host.setManagementServerId(msId); - host.setStorageUrl(startup.getIqn()); - host.setLastPinged(System.currentTimeMillis() >> 10); - if (startup instanceof StartupRoutingCommand) { - final StartupRoutingCommand scc = (StartupRoutingCommand) startup; - host.setCaps(scc.getCapabilities()); - host.setCpus(scc.getCpus()); - host.setTotalMemory(scc.getMemory()); - host.setSpeed(scc.getSpeed()); - HypervisorType hyType = scc.getHypervisorType(); - host.setHypervisorType(hyType); - host.setHypervisorVersion(scc.getHypervisorVersion()); - } else if (startup instanceof StartupStorageCommand) { - final StartupStorageCommand ssc = (StartupStorageCommand) startup; - host.setParent(ssc.getParent()); - host.setTotalSize(ssc.getTotalSize()); - host.setHypervisorType(HypervisorType.None); - if (ssc.getNfsShare() != null) { - host.setStorageUrl(ssc.getNfsShare()); - } - } - if (startup.getStorageIpAddressDeux() != null) { - host.setStorageIpAddressDeux(startup.getStorageIpAddressDeux()); - host.setStorageMacAddressDeux(startup.getStorageMacAddressDeux()); - host.setStorageNetmaskDeux(startup.getStorageNetmaskDeux()); - } - - } - + // protected void upgradeAgent(final Link link, final byte[] request, final // String reason) { // @@ -2212,7 +1330,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, false); } catch (Exception e) { s_logger.warn("Unable to simulate start on resource " + id + " name " + resource.getName(), e); } finally { @@ -2263,7 +1382,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { for (int i = 0; i < cmds.length; i++) { startups[i] = (StartupCommand) cmds[i]; } - attache = handleConnect(link, startups); + attache = handleConnectedAgent(link, startups); } catch (final IllegalArgumentException e) { _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, 0, new Long(0), "Agent from " + startup.getPrivateIpAddress() + " is unable to connect due to " + e.getMessage(), "Agent from " + startup.getPrivateIpAddress() + " is unable to connect with " + request + " because of " + e.getMessage()); @@ -2336,9 +1455,10 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { final String reason = shutdown.getReason(); s_logger.info("Host " + attache.getId() + " has informed us that it is shutting down with reason " + reason + " and detail " + shutdown.getDetail()); if (reason.equals(ShutdownCommand.Update)) { - disconnect(attache, Event.UpdateNeeded, false); + //disconnectWithoutInvestigation(attache, Event.UpdateNeeded); + throw new CloudRuntimeException("Agent update not implemented"); } else if (reason.equals(ShutdownCommand.Requested)) { - disconnect(attache, Event.ShutdownRequested, false); + disconnectWithoutInvestigation(attache, Event.ShutdownRequested); } return; } else if (cmd instanceof AgentControlCommand) { @@ -2435,7 +1555,7 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { final Link link = task.getLink(); final AgentAttache attache = (AgentAttache) link.attachment(); if (attache != null) { - disconnect(attache, Event.AgentDisconnected, true); + disconnectWithInvestigation(attache, Event.AgentDisconnected); } else { s_logger.info("Connection from " + link.getIpAddress() + " closed but no cleanup was done."); link.close(); @@ -2452,4 +1572,125 @@ 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; + } + + @Override + public boolean agentStatusTransitTo(HostVO host, Status.Event e, long msId) { + if (status_logger.isDebugEnabled()) { + ResourceState state = host.getResourceState(); + StringBuilder msg = new StringBuilder("Transition:"); + msg.append("[Resource state = ").append(state); + msg.append(", Agent event = ").append(e.toString()); + msg.append(", Host id = ").append(host.getId()).append(", name = " + host.getName()).append("]"); + status_logger.debug(msg); + } + + host.setManagementServerId(msId); + try { + return _statusStateMachine.transitTo(host, e, host.getId(), _hostDao); + } catch (NoTransitionException e1) { + status_logger.debug("Cannot transit agent status with event " + e + " for host " + host.getId() + ", name=" + host.getName()+ ", 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()); + } + } + + + @Override + public boolean disconnectAgent(HostVO host, Status.Event e, long msId) { + host.setDisconnectedOn(new Date()); + if (e.equals(Status.Event.Remove)) { + host.setGuid(null); + host.setClusterId(null); + } + + return agentStatusTransitTo(host, e, msId); + } + + protected void disconnectWithoutInvestigation(AgentAttache attache, final Status.Event event) { + _executor.submit(new DisconnectTask(attache, event, false)); + } + + protected void disconnectWithInvestigation(AgentAttache attache, final Status.Event event) { + _executor.submit(new DisconnectTask(attache, event, true)); + } + + private void disconnectInternal(final long hostId, final Status.Event event, boolean invstigate) { + AgentAttache attache = findAttache(hostId); + + if (attache != null) { + if (!invstigate) { + disconnectWithoutInvestigation(attache, event); + } else { + disconnectWithInvestigation(attache, event); + } + } else { + /* Agent is still in connecting process, don't allow to disconnect right away */ + if (tapLoadingAgents(hostId, TapAgentsAction.Contains)) { + s_logger.info("Host " + hostId + " is being loaded so no disconnects needed."); + return; + } + + HostVO host = _hostDao.findById(hostId); + if (host != null && host.getRemoved() == null) { + disconnectAgent(host, event, _nodeId); + } + } + } + + @Override + public void disconnectWithInvestigation(final long hostId, final Status.Event event) { + disconnectInternal(hostId, event, true); + } + + @Override + public void disconnectWithoutInvestigation(final long hostId, final Status.Event event) { + disconnectInternal(hostId, event, false); + } + + @Override + public AgentAttache handleDirectConnectAgent(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance) throws ConnectionException { + AgentAttache attache; + + attache = createAttacheForDirectConnect(host, resource); + 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); + attache = notifyMonitorsOfConnection(attache, cmds, forRebalance); + + 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); + } + } + + @Override + public void pullAgentOutMaintenance(long hostId) { + AgentAttache attache = findAttache(hostId); + if (attache != null) { + attache.setMaintenanceMode(false); + } + } } diff --git a/server/src/com/cloud/agent/manager/AgentMonitor.java b/server/src/com/cloud/agent/manager/AgentMonitor.java index a6bc60954f1..682d550a468 100755 --- a/server/src/com/cloud/agent/manager/AgentMonitor.java +++ b/server/src/com/cloud/agent/manager/AgentMonitor.java @@ -42,15 +42,21 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.Status.Event; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; import com.cloud.utils.component.Inject; import com.cloud.utils.db.ConnectionConcierge; import com.cloud.utils.db.DB; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteriaService; import com.cloud.utils.time.InaccurateClock; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.dao.VMInstanceDao; public class AgentMonitor extends Thread implements Listener { private static Logger s_logger = Logger.getLogger(AgentMonitor.class); + private static Logger status_Logger = Logger.getLogger(Status.class); private long _pingTimeout; private HostDao _hostDao; private boolean _stop; @@ -63,6 +69,9 @@ public class AgentMonitor extends Thread implements Listener { private ConnectionConcierge _concierge; @Inject ClusterDao _clusterDao; + @Inject + ResourceManager _resourceMgr; + // private ConnectionConcierge _concierge; private Map _pingMap; @@ -130,13 +139,26 @@ public class AgentMonitor extends Thread implements Listener { } try { - List behindAgents = findAgentsBehindOnPing(); for (Long agentId : behindAgents) { - _agentMgr.disconnect(agentId, Event.PingTimeout, true); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class, ResourceState.class); + sc.selectField(sc.getEntity().getResourceState()); + sc.addAnd(sc.getEntity().getId(), Op.EQ, agentId); + ResourceState resourceState = sc.find(); + if (resourceState == ResourceState.Disabled || resourceState == ResourceState.Maintenance || resourceState == ResourceState.Unmanaged || resourceState == ResourceState.ErrorInMaintenance) { + /* Host is in non-operation state, so no investigation and direct put agent to Disconnected */ + status_Logger.debug("Ping timeout but host " + agentId + " is in resource state of " + resourceState + ", so no investigation"); + _agentMgr.disconnectWithoutInvestigation(agentId, Event.ShutdownRequested); + } else { + status_Logger.debug("Ping timeout for host " + agentId + ", do invstigation"); + _agentMgr.disconnectWithInvestigation(agentId, Event.PingTimeout); + } } - List hosts = _hostDao.listByStatus(Status.PrepareForMaintenance, Status.ErrorInMaintenance); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getResourceState(), Op.IN, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance); + List hosts = sc.list(); + for (HostVO host : hosts) { long hostId = host.getId(); DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId()); @@ -148,7 +170,7 @@ public class AgentMonitor extends Thread implements Listener { List vosMigrating = _vmDao.listVmsMigratingFromHost(hostId); if (vos.isEmpty() && vosMigrating.isEmpty()) { _alertMgr.sendAlert(AlertManager.ALERT_TYPE_HOST, host.getDataCenterId(), host.getPodId(), "Migration Complete for host " + hostDesc, "Host [" + hostDesc + "] is ready for maintenance"); - _hostDao.updateStatus(host, Event.PreparationComplete, _msId); + _resourceMgr.resourceStateTransitTo(host, ResourceState.Event.InternalEnterMaintenance, _msId); } } } @@ -227,7 +249,7 @@ public class AgentMonitor extends Thread implements Listener { s_logger.info("Asking agent mgr to investgate why host " + host.getId() + " is behind on ping. last ping time: " + host.getLastPinged()); } - _agentMgr.disconnect(host.getId(), Event.PingTimeout, true); + _agentMgr.disconnectWithInvestigation(host.getId(), Event.PingTimeout); } } diff --git a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java index ac39c017841..cc464b07c2d 100755 --- a/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/ClusteredAgentManagerImpl.java @@ -58,6 +58,7 @@ import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.Status.Event; @@ -71,7 +72,10 @@ import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteriaService; import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.nio.Link; import com.cloud.utils.nio.Task; @@ -102,6 +106,9 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust @Inject(adapter = AgentLoadBalancerPlanner.class) protected Adapters _lbPlanners; + + @Inject + protected AgentManager _agentMgr; protected ClusteredAgentManagerImpl() { super(); @@ -206,35 +213,6 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust return new ClusteredAgentHandler(type, link, data); } - @Override - public boolean cancelMaintenance(final long hostId) { - try { - Boolean result = _clusterMgr.propagateAgentEvent(hostId, Event.ResetRequested); - - if (result != null) { - return result; - } - } catch (AgentUnavailableException e) { - return false; - } - - return super.cancelMaintenance(hostId); - } - - @Override - public boolean disconnect(final long hostId) { - try { - Boolean result = _clusterMgr.propagateAgentEvent(hostId, Event.PrepareUnmanaged); - - if (result != null) { - return result; - } - } catch (AgentUnavailableException e) { - return false; - } - return super.disconnect(hostId); - } - protected AgentAttache createAttache(long id) { s_logger.debug("create forwarding ClusteredAgentAttache for " + id); final AgentAttache attache = new ClusteredAgentAttache(this, id); @@ -250,15 +228,14 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } @Override - protected AgentAttache createAttache(long id, HostVO server, Link link) { - s_logger.debug("create ClusteredAgentAttache for " + id); - final AgentAttache attache = new ClusteredAgentAttache(this, id, link, server.getStatus() == Status.Maintenance || server.getStatus() == Status.ErrorInMaintenance - || server.getStatus() == Status.PrepareForMaintenance); + protected AgentAttache createAttacheForConnect(HostVO host, Link link) { + s_logger.debug("create ClusteredAgentAttache for " + host.getId()); + final AgentAttache attache = new ClusteredAgentAttache(this, host.getId(), link, host.isInMaintenanceStates()); link.attach(attache); AgentAttache old = null; synchronized (_agents) { - old = _agents.get(id); - _agents.put(id, attache); + old = _agents.get(host.getId()); + _agents.put(host.getId(), attache); } if (old != null) { old.disconnect(Status.Removed); @@ -267,17 +244,16 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } @Override - protected AgentAttache createAttache(long id, HostVO server, ServerResource resource) { + protected AgentAttache createAttacheForDirectConnect(HostVO host, ServerResource resource) { if (resource instanceof DummySecondaryStorageResource) { - return new DummyAttache(this, id, false); + return new DummyAttache(this, host.getId(), false); } - s_logger.debug("create ClusteredDirectAgentAttache for " + id); - final DirectAgentAttache attache = new ClusteredDirectAgentAttache(this, id, _nodeId, resource, server.getStatus() == Status.Maintenance || server.getStatus() == Status.ErrorInMaintenance - || server.getStatus() == Status.PrepareForMaintenance, this); + s_logger.debug("create ClusteredDirectAgentAttache for " + host.getId()); + final DirectAgentAttache attache = new ClusteredDirectAgentAttache(this, host.getId(), _nodeId, resource, host.isInMaintenanceStates(), this); AgentAttache old = null; synchronized (_agents) { - old = _agents.get(id); - _agents.put(id, attache); + old = _agents.get(host.getId()); + _agents.put(host.getId(), attache); } if (old != null) { old.disconnect(Status.Removed); @@ -286,23 +262,31 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } @Override - protected boolean handleDisconnect(AgentAttache attache, Status.Event event, boolean investigate) { - return handleDisconnect(attache, event, investigate, true); + protected boolean handleDisconnectWithoutInvestigation(AgentAttache attache, Status.Event event) { + return handleDisconnect(attache, event, false, true); } - + + @Override + protected boolean handleDisconnectWithInvestigation(AgentAttache attache, Status.Event event) { + return handleDisconnect(attache, event, true, true); + } + protected boolean handleDisconnect(AgentAttache agent, Status.Event event, boolean investigate, boolean broadcast) { - if (agent == null) { - return true; + boolean res; + if (!investigate) { + res = super.handleDisconnectWithoutInvestigation(agent, event); + } else { + res = super.handleDisconnectWithInvestigation(agent, event); } - if (super.handleDisconnect(agent, event, investigate)) { - if (broadcast) { - notifyNodesInCluster(agent); - } - return true; - } else { - return false; - } + if (res) { + if (broadcast) { + notifyNodesInCluster(agent); + } + return true; + } else { + return false; + } } @Override @@ -323,65 +307,19 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust } @Override - public boolean maintain(final long hostId) throws AgentUnavailableException { - Boolean result = _clusterMgr.propagateAgentEvent(hostId, Event.MaintenanceRequested); - if (result != null) { - return result; - } - - return super.maintain(hostId); - } - - @Override - public boolean reconnect(final long hostId) throws AgentUnavailableException { - Boolean result = _clusterMgr.propagateAgentEvent(hostId, Event.ShutdownRequested); - if (result != null) { - return result; - } - - return super.reconnect(hostId); - } - - @Override - @DB - public boolean deleteHost(long hostId, boolean isForced, boolean forceDestroy, User caller) { + public boolean reconnect(final long hostId) { + Boolean result; try { - Boolean result = _clusterMgr.propagateAgentEvent(hostId, Event.Remove); - if (result != null) { - return result; - } + result = _clusterMgr.propagateAgentEvent(hostId, Event.ShutdownRequested); + if (result != null) { + return result; + } } catch (AgentUnavailableException e) { - return false; + s_logger.debug("cannot propagate agent reconnect because agent is not available", e); + return false; } - - return super.deleteHost(hostId, isForced, forceDestroy, caller); - } - - @Override - public boolean updateHostPassword(UpdateHostPasswordCmd upasscmd) { - if (upasscmd.getClusterId() == null) { - // update agent attache password - try { - Boolean result = _clusterMgr.propagateAgentEvent(upasscmd.getHostId(), Event.UpdatePassword); - if (result != null) { - return result; - } - } catch (AgentUnavailableException e) { - } - } else { - // get agents for the cluster - List hosts = _hostDao.listByCluster(upasscmd.getClusterId()); - for (HostVO h : hosts) { - try { - Boolean result = _clusterMgr.propagateAgentEvent(h.getId(), Event.UpdatePassword); - if (result != null) { - return result; - } - } catch (AgentUnavailableException e) { - } - } - } - return super.updateHostPassword(upasscmd); + + return super.reconnect(hostId); } public void notifyNodesInCluster(AgentAttache attache) { @@ -775,7 +713,10 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust public void startRebalanceAgents() { s_logger.debug("Management server " + _nodeId + " is asking other peers to rebalance their agents"); List allMS = _mshostDao.listBy(ManagementServerHost.State.Up); - List allManagedAgents = _hostDao.listManagedRoutingAgents(); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getManagementServerId(), Op.NNULL); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing); + List allManagedAgents = sc.list(); int avLoad = 0; @@ -1087,7 +1028,7 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust s_logger.debug("Updating host id=" + hostId + " with the status " + Status.Rebalancing); host.setManagementServerId(null); - _hostDao.updateStatus(host, Event.StartAgentRebalance, _nodeId); + _agentMgr.agentStatusTransitTo(host, Event.StartAgentRebalance, _nodeId); _hostTransferDao.startAgentTransfer(hostId); txn.commit(); diff --git a/server/src/com/cloud/agent/manager/DirectAgentAttache.java b/server/src/com/cloud/agent/manager/DirectAgentAttache.java old mode 100644 new mode 100755 index bfc02f9bbf6..916603374cb --- a/server/src/com/cloud/agent/manager/DirectAgentAttache.java +++ b/server/src/com/cloud/agent/manager/DirectAgentAttache.java @@ -143,7 +143,7 @@ public class DirectAgentAttache extends AgentAttache { PingCommand cmd = resource.getCurrentStatus(_id); if (cmd == null) { s_logger.warn("Unable to get current status on " + _id); - _mgr.disconnect(DirectAgentAttache.this, Event.AgentDisconnected, true); + _mgr.disconnectWithInvestigation(DirectAgentAttache.this, Event.AgentDisconnected); return; } if (s_logger.isDebugEnabled()) { diff --git a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java index b591dcb8ff3..ac68123a67a 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java @@ -41,6 +41,7 @@ import com.cloud.host.dao.HostDetailsDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.offering.ServiceOffering; +import com.cloud.resource.ResourceManager; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.GuestOSVO; @@ -77,7 +78,8 @@ public class FirstFitAllocator implements HostAllocator { @Inject GuestOSDao _guestOSDao = null; @Inject GuestOSCategoryDao _guestOSCategoryDao = null; @Inject HypervisorCapabilitiesDao _hypervisorCapabilitiesDao = null; - @Inject VMInstanceDao _vmInstanceDao = null; + @Inject VMInstanceDao _vmInstanceDao = null; + @Inject ResourceManager _resourceMgr; float _factor = 1; protected String _allocationAlgorithm = "random"; @Inject CapacityManager _capacityMgr; @@ -115,7 +117,7 @@ public class FirstFitAllocator implements HostAllocator { List clusterHosts = new ArrayList(); if(hostTagOnOffering == null && hostTagOnTemplate == null){ - clusterHosts = _hostDao.listBy(type, clusterId, podId, dcId); + clusterHosts = _resourceMgr.listAllUpAndEnabledHosts(type, clusterId, podId, dcId); }else{ List hostsMatchingOfferingTag = new ArrayList(); List hostsMatchingTemplateTag = new ArrayList(); @@ -193,14 +195,7 @@ public class FirstFitAllocator implements HostAllocator { } continue; } - - if(host.getHostAllocationState() != Host.HostAllocationState.Enabled){ - if (s_logger.isDebugEnabled()) { - s_logger.debug("Host name: " + host.getName() + ", hostId: "+ host.getId() +" is in " + host.getHostAllocationState().name() + " state, skipping this and trying other available hosts"); - } - continue; - } - + //find number of guest VMs occupying capacity on this host. Long vmCount = _vmInstanceDao.countRunningByHostId(host.getId()); Long maxGuestLimit = getHostMaxGuestLimit(host); diff --git a/server/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java index 72f889ec3de..6d390eff4e2 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java @@ -34,6 +34,7 @@ import com.cloud.host.Host.Type; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.offering.ServiceOffering; +import com.cloud.resource.ResourceManager; import com.cloud.uservm.UserVm; import com.cloud.utils.component.ComponentLocator; import com.cloud.vm.VirtualMachine; @@ -44,6 +45,7 @@ public class RandomAllocator implements HostAllocator { private static final Logger s_logger = Logger.getLogger(RandomAllocator.class); private String _name; private HostDao _hostDao; + private ResourceManager _resourceMgr; @Override public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, @@ -78,7 +80,7 @@ public class RandomAllocator implements HostAllocator { if(hostTag != null){ hosts = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTag); }else{ - hosts = _hostDao.listBy(type, clusterId, podId, dcId); + hosts = _resourceMgr.listAllUpAndEnabledHosts(type, clusterId, podId, dcId); } s_logger.debug("Random Allocator found " + hosts.size() + " hosts"); @@ -94,13 +96,6 @@ public class RandomAllocator implements HostAllocator { break; } - if(host.getHostAllocationState() != Host.HostAllocationState.Enabled){ - if (s_logger.isDebugEnabled()) { - s_logger.debug("Host name: " + host.getName() + ", hostId: "+ host.getId() +" is in " + host.getHostAllocationState().name() + " state, skipping this and trying other available hosts"); - } - continue; - } - if (!avoid.shouldAvoid(host)) { suitableHosts.add(host); }else{ @@ -126,6 +121,7 @@ public class RandomAllocator implements HostAllocator { public boolean configure(String name, Map params) { ComponentLocator locator = ComponentLocator.getCurrentLocator(); _hostDao = locator.getDao(HostDao.class); + _resourceMgr = locator.getManager(ResourceManager.class); if (_hostDao == null) { s_logger.error("Unable to get host dao."); return false; diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index b67e79032f6..df47ee53889 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -590,7 +590,7 @@ public class ApiResponseHelper implements ResponseGenerator { hostResponse.setEvents(events); } - hostResponse.setAllocationState(host.getHostAllocationState().toString()); + hostResponse.setAllocationState(host.getResourceState().toString()); hostResponse.setObjectName("host"); diff --git a/server/src/com/cloud/baremetal/BareMetalDiscoverer.java b/server/src/com/cloud/baremetal/BareMetalDiscoverer.java index 0c195339565..9d269401627 100755 --- a/server/src/com/cloud/baremetal/BareMetalDiscoverer.java +++ b/server/src/com/cloud/baremetal/BareMetalDiscoverer.java @@ -27,14 +27,17 @@ import java.util.Map; import java.util.UUID; import javax.ejb.Local; +import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import com.cloud.agent.api.StartupCommand; import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.exception.DiscoveryException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; @@ -42,18 +45,38 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Network; import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.utils.component.Inject; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.dao.VMInstanceDao; @Local(value=Discoverer.class) -public class BareMetalDiscoverer extends DiscovererBase implements Discoverer { +public class BareMetalDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(BareMetalDiscoverer.class); @Inject ClusterDao _clusterDao; @Inject protected HostDao _hostDao; @Inject DataCenterDao _dcDao; + @Inject VMInstanceDao _vmDao = null; + @Inject ResourceManager _resourceMgr; + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); + return super.configure(name, params); + } + + @Override + public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); + return super.stop(); + } + @Override public Map> find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List hostTags) throws DiscoveryException { @@ -179,4 +202,34 @@ public class BareMetalDiscoverer extends DiscovererBase implements Discoverer { return Hypervisor.HypervisorType.BareMetal; } + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + // TODO Auto-generated method stub + return null; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + if (host.getType() != Host.Type.Routing || host.getHypervisorType() != HypervisorType.BareMetal) { + return null; + } + + List deadVms = _vmDao.listByLastHostId(host.getId()); + for (VMInstanceVO vm : deadVms) { + if (vm.getState() == State.Running || vm.getHostId() != null) { + throw new CloudRuntimeException("VM " + vm.getId() + "is still running on host " + host.getId()); + } + _vmDao.remove(vm.getId()); + } + + return new DeleteHostAnswer(true); + } + } diff --git a/server/src/com/cloud/baremetal/BareMetalPingServiceImpl.java b/server/src/com/cloud/baremetal/BareMetalPingServiceImpl.java old mode 100644 new mode 100755 index 1878b305f9e..eb977712afa --- a/server/src/com/cloud/baremetal/BareMetalPingServiceImpl.java +++ b/server/src/com/cloud/baremetal/BareMetalPingServiceImpl.java @@ -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) { @@ -62,7 +65,7 @@ public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId); } - List pxeServers = _hostDao.listBy(Host.Type.PxeServer, null, podId, zoneId); + List pxeServers = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, podId, zoneId); if (pxeServers.size() != 0) { throw new InvalidParameterValueException("Already had a PXE server in Pod: " + podId + " zone: " + zoneId); } @@ -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"); } diff --git a/server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java b/server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java old mode 100644 new mode 100755 index 4d2d5c1ffb7..b3a5eede4d3 --- a/server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java +++ b/server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java @@ -18,6 +18,7 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceManager; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; @@ -34,6 +35,7 @@ import com.cloud.utils.exception.CloudRuntimeException; public class BareMetalTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter { private final static Logger s_logger = Logger.getLogger(BareMetalTemplateAdapter.class); @Inject HostDao _hostDao; + @Inject ResourceManager _resourceMgr; @Override public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException { @@ -43,13 +45,13 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem if (profile.getZoneId() == null || profile.getZoneId() == -1) { List dcs = _dcDao.listAllIncludingRemoved(); for (DataCenterVO dc : dcs) { - List pxeServers = _hostDao.listAllBy(Host.Type.PxeServer, dc.getId()); + List pxeServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.PxeServer, dc.getId()); if (pxeServers.size() == 0) { throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + dc.getName()); } } } else { - List pxeServers = _hostDao.listAllBy(Host.Type.PxeServer, profile.getZoneId()); + List pxeServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.PxeServer, profile.getZoneId()); if (pxeServers.size() == 0) { throw new CloudRuntimeException("Please add PXE server before adding baremetal template in zone " + profile.getZoneId()); } @@ -86,7 +88,7 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem if (zoneId == null || zoneId == -1) { List dcs = _dcDao.listAllIncludingRemoved(); for (DataCenterVO dc : dcs) { - HostVO pxe = _hostDao.listAllBy(Host.Type.PxeServer, dc.getId()).get(0); + HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.PxeServer, dc.getId()).get(0); vmTemplateHost = _tmpltHostDao.findByHostTemplate(dc.getId(), template.getId()); if (vmTemplateHost == null) { @@ -97,7 +99,7 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem } } } else { - HostVO pxe = _hostDao.listAllBy(Host.Type.PxeServer, zoneId).get(0); + HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.PxeServer, zoneId).get(0); vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, null, template.getUrl()); _tmpltHostDao.persist(vmTemplateHost); diff --git a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java index 95678965dff..97d5f52f539 100755 --- a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java +++ b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java @@ -64,6 +64,7 @@ import com.cloud.network.Network; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.TrafficType; import com.cloud.org.Grouping; +import com.cloud.resource.ResourceManager; import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.Storage; import com.cloud.storage.Storage.TemplateType; @@ -108,7 +109,8 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet StateListener { private static final Logger s_logger = Logger.getLogger(BareMetalVmManagerImpl.class); private ConfigurationDao _configDao; - @Inject PxeServerManager _pxeMgr; + @Inject PxeServerManager _pxeMgr; + @Inject ResourceManager _resourceMgr; @Inject (adapter=TemplateAdapter.class) protected Adapters _adapters; @@ -161,7 +163,7 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet throw new InvalidParameterValueException("Cannot find host with id " + hostId); } - List pxes = _hostDao.listBy(Host.Type.PxeServer, null, host.getPodId(), host.getDataCenterId()); + List pxes = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, host.getPodId(), host.getDataCenterId()); if (pxes.size() == 0) { throw new CloudRuntimeException("Please add PXE server in Pod before taking image"); } @@ -400,7 +402,7 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet long vmId = cmd.getEntityId(); UserVmVO vm = _vmDao.findById(vmId); - List servers = _hostDao.listBy(Host.Type.PxeServer, vm.getDataCenterIdToDeployIn()); + List servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, vm.getDataCenterIdToDeployIn()); if (servers.size() == 0) { throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone"); } @@ -469,7 +471,7 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet } s_logger.debug("This is a PXE start, prepare PXE server first"); - List servers = _hostDao.listBy(Host.Type.PxeServer, vm.getDataCenterIdToDeployIn()); + List servers = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.PxeServer, dest.getDataCenter().getId()); if (servers.size() == 0) { throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone"); } diff --git a/server/src/com/cloud/baremetal/ExternalDhcpManagerImpl.java b/server/src/com/cloud/baremetal/ExternalDhcpManagerImpl.java index 0d6ddfff729..ce9843a65d3 100755 --- a/server/src/com/cloud/baremetal/ExternalDhcpManagerImpl.java +++ b/server/src/com/cloud/baremetal/ExternalDhcpManagerImpl.java @@ -39,6 +39,7 @@ 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.StartupExternalDhcpCommand; import com.cloud.agent.api.routing.DhcpEntryCommand; import com.cloud.agent.manager.Commands; import com.cloud.baremetal.ExternalDhcpEntryListener.DhcpEntryState; @@ -59,7 +60,10 @@ 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.ResourceStateAdapter; import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.utils.component.Inject; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; @@ -73,7 +77,7 @@ import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.UserVmDao; @Local(value = {ExternalDhcpManager.class}) -public class ExternalDhcpManagerImpl implements ExternalDhcpManager { +public class ExternalDhcpManagerImpl implements ExternalDhcpManager, ResourceStateAdapter { private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalDhcpManagerImpl.class); protected String _name; @Inject DataCenterDao _dcDao; @@ -81,9 +85,11 @@ public class ExternalDhcpManagerImpl implements ExternalDhcpManager { @Inject AgentManager _agentMgr; @Inject HostPodDao _podDao; @Inject UserVmDao _userVmDao; + @Inject ResourceManager _resourceMgr; @Override public boolean configure(String name, Map params) throws ConfigurationException { + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -94,6 +100,7 @@ public class ExternalDhcpManagerImpl implements ExternalDhcpManager { @Override public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); return true; } @@ -119,7 +126,7 @@ public class ExternalDhcpManagerImpl implements ExternalDhcpManager { throw new InvalidParameterValueException("Could not find pod with ID: " + podId); } - List dhcps = _hostDao.listBy(Host.Type.ExternalDhcp, null, podId, zoneId); + List dhcps = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.ExternalDhcp, null, podId, zoneId); if (dhcps.size() != 0) { throw new InvalidParameterValueException("Already had a DHCP server in Pod: " + podId + " zone: " + zoneId); } @@ -159,7 +166,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"); } @@ -187,7 +194,7 @@ public class ExternalDhcpManagerImpl implements ExternalDhcpManager { return; } - List servers = _hostDao.listBy(Host.Type.PxeServer, null, vm.getPodIdToDeployIn(), vm.getDataCenterIdToDeployIn()); + List servers = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, vm.getPodIdToDeployIn(), vm.getDataCenterIdToDeployIn()); if (servers.size() != 1) { throw new CloudRuntimeException("Wrong number of PXE server found in zone " + vm.getDataCenterIdToDeployIn() + " Pod " + vm.getPodIdToDeployIn() + ", number is " + servers.size()); @@ -202,7 +209,7 @@ public class ExternalDhcpManagerImpl implements ExternalDhcpManager { ReservationContext context) throws ResourceUnavailableException { Long zoneId = profile.getVirtualMachine().getDataCenterIdToDeployIn(); Long podId = profile.getVirtualMachine().getPodIdToDeployIn(); - List hosts = _hostDao.listBy(Type.ExternalDhcp, null, podId, zoneId); + List hosts = _resourceMgr.listAllUpAndEnabledHosts(Type.ExternalDhcp, null, podId, zoneId); if (hosts.size() == 0) { throw new CloudRuntimeException("No external Dhcp found in zone " + zoneId + " pod " + podId); } @@ -235,4 +242,27 @@ public class ExternalDhcpManagerImpl implements ExternalDhcpManager { throw new ResourceUnavailableException(errMsg + e.getMessage(), DataCenter.class, zoneId); } } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + if (!(startup[0] instanceof StartupExternalDhcpCommand)) { + return null; + } + + host.setType(Host.Type.ExternalDhcp); + return host; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } } diff --git a/server/src/com/cloud/baremetal/PxeServerManagerImpl.java b/server/src/com/cloud/baremetal/PxeServerManagerImpl.java old mode 100644 new mode 100755 index 397fda13344..1a6a498deeb --- a/server/src/com/cloud/baremetal/PxeServerManagerImpl.java +++ b/server/src/com/cloud/baremetal/PxeServerManagerImpl.java @@ -20,6 +20,7 @@ package com.cloud.baremetal; +import java.util.List; import java.util.Map; import javax.ejb.Local; @@ -27,12 +28,18 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupPxeServerCommand; import com.cloud.baremetal.PxeServerManager.PxeServerType; import com.cloud.dc.dao.DataCenterDao; import com.cloud.deploy.DeployDestination; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.uservm.UserVm; import com.cloud.utils.component.Adapters; import com.cloud.utils.component.Inject; @@ -43,20 +50,21 @@ import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfile.Param; @Local(value = {PxeServerManager.class}) -public class PxeServerManagerImpl implements PxeServerManager { +public class PxeServerManagerImpl implements PxeServerManager, ResourceStateAdapter { private static final org.apache.log4j.Logger s_logger = Logger.getLogger(PxeServerManagerImpl.class); protected String _name; @Inject DataCenterDao _dcDao; @Inject HostDao _hostDao; @Inject AgentManager _agentMgr; @Inject ExternalDhcpManager exDhcpMgr; - + @Inject ResourceManager _resourceMgr; @Inject(adapter=PxeServerService.class) protected Adapters _services; @Override public boolean configure(String name, Map params) throws ConfigurationException { _name = name; + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -67,6 +75,7 @@ public class PxeServerManagerImpl implements PxeServerManager { @Override public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); return true; } @@ -115,4 +124,27 @@ public class PxeServerManagerImpl implements PxeServerManager { throw new CloudRuntimeException("Unkown PXE server resource " + host.getResource()); } } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + if (!(startup[0] instanceof StartupPxeServerCommand)) { + return null; + } + + host.setType(Host.Type.PxeServer); + return host; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } } diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 7290b2381c4..18bd9bdeb4b 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -44,6 +44,7 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.offering.ServiceOffering; +import com.cloud.resource.ResourceManager; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.utils.DateUtil; @@ -77,6 +78,8 @@ public class CapacityManagerImpl implements CapacityManager, StateListener allManagedRoutingAgents = _hostDao.listManagedRoutingAgents(); - List allAgents = _hostDao.listAllRoutingAgents(); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getManagementServerId(), Op.NNULL); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing); + List allManagedRoutingAgents = sc.list(); + + sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing); + List allAgents = sc.list(); double allHostsCount = allAgents.size(); double managedHostsCount = allManagedRoutingAgents.size(); if (allHostsCount > 0.0) { @@ -1229,4 +1244,34 @@ public class ClusterManagerImpl implements ClusterManager { public boolean isAgentRebalanceEnabled() { return _agentLBEnabled; } + + @Override + public Boolean propagateResourceEvent(long agentId, ResourceState.Event event) throws AgentUnavailableException { + final String msPeer = getPeerName(agentId); + if (msPeer == null) { + return null; + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Propagating agent change request event:" + event.toString() + " to agent:" + agentId); + } + Command[] cmds = new Command[1]; + cmds[0] = new PropagateResourceEventCommand(agentId, event); + + Answer[] answers = execute(msPeer, agentId, cmds, true); + if (answers == null) { + throw new AgentUnavailableException(agentId); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Result for agent change is " + answers[0].getResult()); + } + + return answers[0].getResult(); + } + + @Override + public boolean executeResourceUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException { + return _resourceMgr.executeUserRequest(hostId, event); + } } diff --git a/server/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java b/server/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java old mode 100644 new mode 100755 index b9b8db2f5cc..9636683076b --- a/server/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java +++ b/server/src/com/cloud/cluster/ClusterServiceServletHttpHandler.java @@ -38,6 +38,7 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.ChangeAgentAnswer; import com.cloud.agent.api.ChangeAgentCommand; import com.cloud.agent.api.Command; +import com.cloud.agent.api.PropagateResourceEventCommand; import com.cloud.agent.api.TransferAgentCommand; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; @@ -240,7 +241,28 @@ public class ClusterServiceServletHttpHandler implements HttpRequestHandler { Answer[] answers = new Answer[1]; answers[0] = new Answer(cmd, result, null); return gson.toJson(answers); - } + } else if (cmds.length == 1 && cmds[0] instanceof PropagateResourceEventCommand) { + PropagateResourceEventCommand cmd = (PropagateResourceEventCommand) cmds[0]; + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Intercepting command for resource event: host " + cmd.getHostId() + " event: " + cmd.getEvent()); + } + boolean result = false; + try { + result = manager.executeResourceUserRequest(cmd.getHostId(), cmd.getEvent()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Result is " + result); + } + + } catch (AgentUnavailableException e) { + s_logger.warn("Agent is unavailable", e); + return null; + } + + Answer[] answers = new Answer[1]; + answers[0] = new Answer(cmd, result, null); + return gson.toJson(answers); + } try { long startTick = System.currentTimeMillis(); diff --git a/server/src/com/cloud/cluster/DummyClusterManagerImpl.java b/server/src/com/cloud/cluster/DummyClusterManagerImpl.java old mode 100644 new mode 100755 index c4218b2b8bb..6275b8b21e7 --- a/server/src/com/cloud/cluster/DummyClusterManagerImpl.java +++ b/server/src/com/cloud/cluster/DummyClusterManagerImpl.java @@ -174,5 +174,17 @@ public class DummyClusterManagerImpl implements ClusterManager { @Override public boolean isAgentRebalanceEnabled() { return false; + } + + @Override + public Boolean propagateResourceEvent(long agentId, com.cloud.resource.ResourceState.Event event) throws AgentUnavailableException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean executeResourceUserRequest(long hostId, com.cloud.resource.ResourceState.Event event) throws AgentUnavailableException { + // TODO Auto-generated method stub + return false; } } diff --git a/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java b/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java old mode 100644 new mode 100755 index d8075ece657..3c05f10e99a --- a/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java +++ b/server/src/com/cloud/cluster/agentlb/ClusterBasedAgentLoadBalancerPlanner.java @@ -30,10 +30,14 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.utils.component.Inject; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteriaService; @Local(value=AgentLoadBalancerPlanner.class) @@ -66,14 +70,21 @@ public class ClusterBasedAgentLoadBalancerPlanner implements AgentLoadBalancerPl @Override public List getHostsToRebalance(long msId, int avLoad) { - List allHosts = _hostDao.listRoutingHostsByManagementServer(msId); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing); + sc.addAnd(sc.getEntity().getManagementServerId(), Op.EQ, msId); + List allHosts = sc.list(); if (allHosts.size() <= avLoad) { s_logger.debug("Agent load = " + allHosts.size() + " for management server " + msId + " doesn't exceed average system agent load = " + avLoad + "; so it doesn't participate in agent rebalancing process"); return null; } - List directHosts = _hostDao.listDirectHostsBy(msId, Status.Up); + sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getManagementServerId(), Op.EQ, msId); + sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); + List directHosts = sc.list(); + if (directHosts.isEmpty()) { s_logger.debug("No direct agents in status " + Status.Up + " exist for the management server " + msId + "; so it doesn't participate in agent rebalancing process"); return null; diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java old mode 100644 new mode 100755 diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java old mode 100644 new mode 100755 index 137d6b0fe0d..4ee86dd27c6 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java @@ -24,6 +24,7 @@ import com.cloud.agent.api.ConsoleProxyLoadReportCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.host.HostVO; import com.cloud.host.Status; +import com.cloud.host.Host.Type; import com.cloud.info.ConsoleProxyInfo; import com.cloud.utils.component.Manager; import com.cloud.vm.ConsoleProxyVO; @@ -58,5 +59,4 @@ public interface ConsoleProxyManager extends Manager { public void onAgentConnect(HostVO host, StartupCommand cmd); public void onAgentDisconnect(long agentId, Status state); - } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java old mode 100644 new mode 100755 index b155abf42b3..2172d4e263e --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -70,6 +70,7 @@ import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; import com.cloud.host.Host.Type; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -88,6 +89,10 @@ import com.cloud.network.NetworkVO; import com.cloud.network.Networks.TrafficType; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.servlet.ConsoleProxyServlet; @@ -112,7 +117,10 @@ import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.db.DB; import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteriaService; import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.events.SubscriptionMgr; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; @@ -149,7 +157,7 @@ import com.google.gson.GsonBuilder; // because sooner or later, it will be driven into Running state // @Local(value = { ConsoleProxyManager.class, ConsoleProxyService.class }) -public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProxyService, Manager, AgentHook, VirtualMachineGuru, SystemVmLoadScanHandler { +public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProxyService, Manager, AgentHook, VirtualMachineGuru, SystemVmLoadScanHandler, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class); private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 seconds @@ -199,6 +207,8 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx StoragePoolDao _storagePoolDao; @Inject UserVmDetailsDao _vmDetailsDao; + @Inject + ResourceManager _resourceMgr; private ConsoleProxyListener _listener; @@ -1000,6 +1010,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx this._loadScanner.stop(); _allocProxyLock.releaseRef(); + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); return true; } @@ -1267,6 +1278,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx _loadScanner = new SystemVmLoadScanner(this); _loadScanner.initScan(STARTUP_DELAY, _capacityScanInterval); + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); if (s_logger.isInfoEnabled()) { s_logger.info("Console Proxy Manager is configured."); @@ -1459,7 +1471,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx long proxyVmId = startupCmd.getProxyVmId(); ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId); assert (consoleProxy != null); - HostVO consoleProxyHost = _hostDao.findConsoleProxyHost(consoleProxy.getHostName(), Type.ConsoleProxy); + HostVO consoleProxyHost = findConsoleProxyHostByName(consoleProxy.getHostName()); Answer answer = _agentMgr.send(consoleProxyHost.getId(), cmd); if (answer == null || !answer.getResult()) { @@ -1657,4 +1669,34 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, ConsoleProx @Override public void onScanEnd() { } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + if (!(cmd[0] instanceof StartupProxyCommand)) { + return null; + } + + host.setType(com.cloud.host.Host.Type.ConsoleProxy); + return host; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + // TODO Auto-generated method stub + return null; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } + + protected HostVO findConsoleProxyHostByName(String name) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.ConsoleProxy); + sc.addAnd(sc.getEntity().getName(), Op.EQ, name); + return sc.find(); + } } diff --git a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java old mode 100644 new mode 100755 index 420570fde58..9b2ab660aa6 --- a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java @@ -27,6 +27,7 @@ import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.host.Host.Type; import com.cloud.host.HostVO; import com.cloud.info.ConsoleProxyInfo; +import com.cloud.resource.ResourceManager; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.vm.VMInstanceVO; @@ -36,11 +37,12 @@ import com.cloud.vm.dao.ConsoleProxyDao; public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager implements ConsoleProxyManager { String _ip = null; @Inject ConsoleProxyDao _proxyDao; + @Inject ResourceManager _resourceMgr; @Override protected HostVO findHost(VMInstanceVO vm) { - List hosts = _hostDao.listBy(Type.ConsoleProxy, vm.getDataCenterIdToDeployIn()); + List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Type.ConsoleProxy, vm.getDataCenterIdToDeployIn()); return hosts.isEmpty() ? null : hosts.get(0); } diff --git a/server/src/com/cloud/deploy/BareMetalPlanner.java b/server/src/com/cloud/deploy/BareMetalPlanner.java old mode 100644 new mode 100755 index 247965388a5..bc34af9e4b7 --- a/server/src/com/cloud/deploy/BareMetalPlanner.java +++ b/server/src/com/cloud/deploy/BareMetalPlanner.java @@ -42,6 +42,7 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.offering.ServiceOffering; import com.cloud.org.Cluster; +import com.cloud.resource.ResourceManager; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.Inject; import com.cloud.utils.exception.CloudRuntimeException; @@ -57,6 +58,7 @@ public class BareMetalPlanner implements DeploymentPlanner { @Inject protected HostDao _hostDao; @Inject protected ConfigurationDao _configDao; @Inject protected CapacityManager _capacityMgr; + @Inject protected ResourceManager _resourceMgr; String _name; @Override @@ -94,7 +96,7 @@ public class BareMetalPlanner implements DeploymentPlanner { int cpu_requested; long ram_requested; HostVO target = null; - List hosts = _hostDao.listByCluster(cluster.getId()); + List hosts = _resourceMgr.listAllHostsInCluster(cluster.getId()); if (hostTag != null) { for (HostVO h : hosts) { _hostDao.loadDetails(h); diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java index bd302c05196..0535fd58fe3 100755 --- a/server/src/com/cloud/deploy/FirstFitPlanner.java +++ b/server/src/com/cloud/deploy/FirstFitPlanner.java @@ -53,6 +53,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.offering.ServiceOffering; import com.cloud.org.Cluster; import com.cloud.org.Grouping; +import com.cloud.resource.ResourceState; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; @@ -177,7 +178,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { if(host == null){ s_logger.debug("The last host of this VM cannot be found"); }else{ - if (host.getStatus() == Status.Up && host.getHostAllocationState() == Host.HostAllocationState.Enabled) { + if (host.getStatus() == Status.Up && host.getResourceState() == ResourceState.Enabled) { if(_capacityMgr.checkIfHostHasCapacity(host.getId(), cpu_requested, ram_requested, true, cpuOverprovisioningFactor, true)){ s_logger.debug("The last host of this VM is UP and has enough capacity"); s_logger.debug("Now checking for suitable pools under zone: "+host.getDataCenterId() +", pod: "+ host.getPodId()+", cluster: "+ host.getClusterId()); @@ -209,7 +210,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { s_logger.debug("The last host of this VM does not have enough capacity"); } }else{ - s_logger.debug("The last host of this VM is not UP or is not enabled, host status is: "+host.getStatus().name() + ", host allocation state is: "+host.getHostAllocationState().name()); + s_logger.debug("The last host of this VM is not UP or is not enabled, host status is: "+host.getStatus().name() + ", host resource state is: "+host.getResourceState()); } } diff --git a/server/src/com/cloud/ha/AbstractInvestigatorImpl.java b/server/src/com/cloud/ha/AbstractInvestigatorImpl.java old mode 100644 new mode 100755 index 238063bc406..b27869021d5 --- a/server/src/com/cloud/ha/AbstractInvestigatorImpl.java +++ b/server/src/com/cloud/ha/AbstractInvestigatorImpl.java @@ -33,9 +33,14 @@ import com.cloud.agent.api.PingTestCommand; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.OperationTimedoutException; import com.cloud.host.Host.Type; +import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceManager; import com.cloud.utils.component.Inject; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteriaService; public abstract class AbstractInvestigatorImpl implements Investigator { private static final Logger s_logger = Logger.getLogger(AbstractInvestigatorImpl.class); @@ -43,6 +48,7 @@ public abstract class AbstractInvestigatorImpl implements Investigator { private String _name = null; @Inject private HostDao _hostDao = null; @Inject private AgentManager _agentMgr = null; + @Inject private ResourceManager _resourceMgr = null; @Override @@ -69,7 +75,12 @@ public abstract class AbstractInvestigatorImpl implements Investigator { // Host.status is up and Host.type is routing protected List findHostByPod(long podId, Long excludeHostId) { - List hostIds = _hostDao.listBy(null, podId, null, Type.Routing, Status.Up); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Type.Routing); + sc.addAnd(sc.getEntity().getPodId(), Op.EQ, podId); + sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); + List hostIds = sc.list(); + if (excludeHostId != null){ hostIds.remove(excludeHostId); } diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java old mode 100644 new mode 100755 index 8bd840d579b..8d9f7ad770e --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -57,6 +57,7 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; import com.cloud.server.ManagementServer; import com.cloud.storage.StorageManager; import com.cloud.storage.dao.GuestOSCategoryDao; @@ -135,6 +136,8 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager, Clu VirtualMachineManager _itMgr; @Inject AccountManager _accountMgr; + @Inject + ResourceManager _resourceMgr; String _instance; ScheduledExecutorService _executor; @@ -548,16 +551,16 @@ public class HighAvailabilityManagerImpl implements HighAvailabilityManager, Clu if (!_itMgr.migrateAway(work.getType(), vmId, srcHostId)) { s_logger.warn("Unable to migrate vm from " + srcHostId); - _agentMgr.maintenanceFailed(srcHostId); + _resourceMgr.maintenanceFailed(srcHostId); } return null; } catch (InsufficientServerCapacityException e) { s_logger.warn("Insufficient capacity for migrating a VM."); - _agentMgr.maintenanceFailed(srcHostId); + _resourceMgr.maintenanceFailed(srcHostId); return (System.currentTimeMillis() >> 10) + _migrateRetryInterval; } catch (VirtualMachineMigrationException e) { s_logger.warn("Looks like VM is still starting, we need to retry migrating the VM later."); - _agentMgr.maintenanceFailed(srcHostId); + _resourceMgr.maintenanceFailed(srcHostId); return (System.currentTimeMillis() >> 10) + _migrateRetryInterval; } } diff --git a/server/src/com/cloud/ha/KVMFencer.java b/server/src/com/cloud/ha/KVMFencer.java old mode 100644 new mode 100755 index 25f9967bbde..9f6804aeda1 --- a/server/src/com/cloud/ha/KVMFencer.java +++ b/server/src/com/cloud/ha/KVMFencer.java @@ -36,6 +36,7 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; import com.cloud.utils.component.Inject; import com.cloud.vm.VMInstanceVO; @@ -46,6 +47,7 @@ public class KVMFencer implements FenceBuilder { @Inject HostDao _hostDao; @Inject AgentManager _agentMgr; + @Inject ResourceManager _resourceMgr; @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -82,7 +84,7 @@ public class KVMFencer implements FenceBuilder { return null; } - List hosts = _hostDao.listByCluster(host.getClusterId()); + List hosts = _resourceMgr.listAllHostsInCluster(host.getClusterId()); FenceCommand fence = new FenceCommand(vm, host); for (HostVO h : hosts) { diff --git a/server/src/com/cloud/ha/XenServerFencer.java b/server/src/com/cloud/ha/XenServerFencer.java old mode 100644 new mode 100755 index d38e5de261d..8acb39920a6 --- a/server/src/com/cloud/ha/XenServerFencer.java +++ b/server/src/com/cloud/ha/XenServerFencer.java @@ -35,6 +35,7 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; import com.cloud.utils.component.Inject; import com.cloud.vm.VMInstanceVO; @@ -45,6 +46,7 @@ public class XenServerFencer implements FenceBuilder { @Inject HostDao _hostDao; @Inject AgentManager _agentMgr; + @Inject ResourceManager _resourceMgr; @Override public Boolean fenceOff(VMInstanceVO vm, HostVO host) { @@ -53,7 +55,7 @@ public class XenServerFencer implements FenceBuilder { return null; } - List hosts = _hostDao.listByCluster(host.getClusterId()); + List hosts = _resourceMgr.listAllHostsInCluster(host.getClusterId()); FenceCommand fence = new FenceCommand(vm, host); for (HostVO h : hosts) { diff --git a/server/src/com/cloud/ha/XenServerInvestigator.java b/server/src/com/cloud/ha/XenServerInvestigator.java old mode 100644 new mode 100755 index 57d70e1e06a..56a93e06572 --- a/server/src/com/cloud/ha/XenServerInvestigator.java +++ b/server/src/com/cloud/ha/XenServerInvestigator.java @@ -31,6 +31,7 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; import com.cloud.vm.VMInstanceVO; @@ -40,6 +41,7 @@ public class XenServerInvestigator extends AdapterBase implements Investigator { private final static Logger s_logger = Logger.getLogger(XenServerInvestigator.class); @Inject HostDao _hostDao; @Inject AgentManager _agentMgr; + @Inject ResourceManager _resourceMgr; protected XenServerInvestigator() { } @@ -51,7 +53,7 @@ public class XenServerInvestigator extends AdapterBase implements Investigator { } CheckOnHostCommand cmd = new CheckOnHostCommand(agent); - List neighbors = _hostDao.listByCluster(agent.getClusterId()); + List neighbors = _resourceMgr.listAllHostsInCluster(agent.getClusterId()); for (HostVO neighbor : neighbors) { if (neighbor.getId() == agent.getId() || neighbor.getHypervisorType() != HypervisorType.XenServer) { continue; diff --git a/server/src/com/cloud/host/dao/HostDao.java b/server/src/com/cloud/host/dao/HostDao.java index 6dba59a2904..4e2bded2e6e 100755 --- a/server/src/com/cloud/host/dao/HostDao.java +++ b/server/src/com/cloud/host/dao/HostDao.java @@ -27,29 +27,16 @@ 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; /** * Data Access Object for server * */ -public interface HostDao extends GenericDao { - List listBy(Host.Type type, Long clusterId, Long podId, long dcId); - - long countBy(long clusterId, Status... statuses); - - List listByDataCenter(long dcId); - List listByHostPod(long podId); - List listByStatus(Status... status); - List listBy(Host.Type type, long dcId); - List listAllBy(Host.Type type, long dcId); - HostVO findSecondaryStorageHost(long dcId); - List listByCluster(long clusterId); - /** - * Lists all secondary storage hosts, across all zones - * @return list of Hosts - */ - List listSecondaryStorageHosts(); +public interface HostDao extends GenericDao, StateDao { + long countBy(long clusterId, ResourceState... states); /** * Mark all hosts associated with a certain management server @@ -61,63 +48,7 @@ public interface HostDao extends GenericDao { List findLostHosts(long timeout); - List findHostsLike(String hostName); - - /** - * Find hosts that are directly connected. - */ - List findDirectlyConnectedHosts(); - - List findAndUpdateDirectAgentToLoad(long lastPingSecondsAfter, Long limit, long managementServerId); - /** - * Mark the host as disconnected if it is in one of these states. - * The management server id is set to null. - * The lastPinged timestamp is set to current. - * The state is set to the state passed in. - * The disconnectedOn timestamp is set to current. - * - * @param host host to be marked - * @param state state to be set to. - * @param ifStates only if it is one of these states. - * @return true if it's updated; false if not. - */ - boolean disconnect(HostVO host, Event event, long msId); - - boolean connect(HostVO host, long msId); - - HostVO findByStorageIpAddressInDataCenter(long dcId, String privateIpAddress); - HostVO findByPrivateIpAddressInDataCenter(long dcId, String privateIpAddress); - - public HostVO findByGuid(String guid); - - public HostVO findByName(String name); - - - /** - * find all hosts of a certain type in a data center - * @param type - * @param routingCapable - * @param dcId - * @return - */ - List listByTypeDataCenter(Host.Type type, long dcId); - - /** - * find all hosts of a particular type - * @param type - * @return - */ - List listByType(Type type); - - /** - * update the host and changes the status depending on the Event and - * the current status. If the status changed between - * @param host host object to change - * @param event event that happened. - * @param management server who's making this update - * @return true if updated; false if not. - */ - boolean updateStatus(HostVO host, Event event, long msId); + List findAndUpdateDirectAgentToLoad(long lastPingSecondsAfter, Long limit, long managementServerId); List getRunningHostCounts(Date cutTime); @@ -127,56 +58,13 @@ public interface HostDao extends GenericDao { void saveDetails(HostVO host); - HostVO findConsoleProxyHost(String name, Type type); - - List getAvailHypervisorInZone(Long hostId, Long zoneId); - - /** - * Returns a list of host ids given the conditions. - * @param dataCenterId if specified, then must be in this data center. - * @param podId if specified, then must be in this pod. - * @param clusterId if specified, then must be in this cluster. - * @param hostType TODO - * @param statuses the host needs to be in. - * @return ids of the host meeting the search parameters. - */ - List listBy(Long dataCenterId, Long podId, Long clusterId, Type hostType, Status... statuses); - - List listBy(Long clusterId, Long podId, long dcId); - void loadHostTags(HostVO host); List listByHostTag(Host.Type type, Long clusterId, Long podId, long dcId, String hostTag); long countRoutingHostsByDataCenter(long dcId); - List listSecondaryStorageHosts(long dataCenterId); - - boolean directConnect(HostVO host, long msId); - - List listDirectHostsBy(long msId, Status status); - - List listManagedDirectAgents(); - - List listManagedRoutingAgents(); - - HostVO findTrafficMonitorHost(); - - List listLocalSecondaryStorageHosts(); - - List listLocalSecondaryStorageHosts(long dataCenterId); - - List listAllSecondaryStorageHosts(long dataCenterId); - - List listRoutingHostsByManagementServer(long msId); - - List listSecondaryStorageVM(long dcId); - - List listAllRoutingAgents(); - List findAndUpdateApplianceToLoad(long lastPingSecondsAfter, long managementServerId); - List listByInAllStatus(Type type, Long clusterId, Long podId, long dcId); - - 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 5d16677f1d1..dac3fff679c 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; @@ -67,6 +68,8 @@ import com.cloud.utils.exception.CloudRuntimeException; @TableGenerator(name = "host_req_sq", table = "op_host", pkColumnName = "id", valueColumnName = "sequence", allocationSize = 1) public class HostDaoImpl extends GenericDaoBase implements HostDao { private static final Logger s_logger = Logger.getLogger(HostDaoImpl.class); + private static final Logger status_logger = Logger.getLogger(Status.class); + private static final Logger state_logger = Logger.getLogger(ResourceState.class); protected final SearchBuilder TypePodDcStatusSearch; @@ -82,6 +85,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao protected final SearchBuilder PodSearch; protected final SearchBuilder TypeSearch; protected final SearchBuilder StatusSearch; + protected final SearchBuilder ResourceStateSearch; protected final SearchBuilder NameLikeSearch; protected final SearchBuilder NameSearch; protected final SearchBuilder SequenceSearch; @@ -106,6 +110,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao protected final SearchBuilder RoutingSearch; protected final Attribute _statusAttr; + protected final Attribute _resourceStateAttr; protected final Attribute _msIdAttr; protected final Attribute _pingTimeAttr; @@ -119,7 +124,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao MaintenanceCountSearch = createSearchBuilder(); MaintenanceCountSearch.and("cluster", MaintenanceCountSearch.entity().getClusterId(), SearchCriteria.Op.EQ); - MaintenanceCountSearch.and("status", MaintenanceCountSearch.entity().getStatus(), SearchCriteria.Op.IN); + MaintenanceCountSearch.and("resourceState", MaintenanceCountSearch.entity().getResourceState(), SearchCriteria.Op.IN); MaintenanceCountSearch.done(); TypePodDcStatusSearch = createSearchBuilder(); @@ -129,12 +134,13 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao TypePodDcStatusSearch.and("dc", entity.getDataCenterId(), SearchCriteria.Op.EQ); TypePodDcStatusSearch.and("cluster", entity.getClusterId(), SearchCriteria.Op.EQ); TypePodDcStatusSearch.and("status", entity.getStatus(), SearchCriteria.Op.EQ); + TypePodDcStatusSearch.and("resourceState", entity.getResourceState(), SearchCriteria.Op.EQ); TypePodDcStatusSearch.done(); MsStatusSearch = createSearchBuilder(); MsStatusSearch.and("ms", MsStatusSearch.entity().getManagementServerId(), SearchCriteria.Op.EQ); MsStatusSearch.and("type", MsStatusSearch.entity().getType(), SearchCriteria.Op.EQ); - MsStatusSearch.and("statuses", MsStatusSearch.entity().getStatus(), SearchCriteria.Op.NIN); + MsStatusSearch.and("resourceState", MsStatusSearch.entity().getResourceState(), SearchCriteria.Op.NIN); MsStatusSearch.done(); TypeDcSearch = createSearchBuilder(); @@ -152,6 +158,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao TypeDcStatusSearch.and("type", TypeDcStatusSearch.entity().getType(), SearchCriteria.Op.EQ); TypeDcStatusSearch.and("dc", TypeDcStatusSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); TypeDcStatusSearch.and("status", TypeDcStatusSearch.entity().getStatus(), SearchCriteria.Op.EQ); + TypeDcStatusSearch.and("resourceState", TypeDcStatusSearch.entity().getResourceState(), SearchCriteria.Op.EQ); TypeDcStatusSearch.done(); IdStatusSearch = createSearchBuilder(); @@ -198,6 +205,10 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao StatusSearch = createSearchBuilder(); StatusSearch.and("status", StatusSearch.entity().getStatus(), SearchCriteria.Op.IN); StatusSearch.done(); + + ResourceStateSearch = createSearchBuilder(); + ResourceStateSearch.and("resourceState", ResourceStateSearch.entity().getResourceState(), SearchCriteria.Op.IN); + ResourceStateSearch.done(); NameLikeSearch = createSearchBuilder(); NameLikeSearch.and("name", NameLikeSearch.entity().getName(), SearchCriteria.Op.LIKE); @@ -216,13 +227,14 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao DirectlyConnectedSearch.and("resource", DirectlyConnectedSearch.entity().getResource(), SearchCriteria.Op.NNULL); DirectlyConnectedSearch.and("ms", DirectlyConnectedSearch.entity().getManagementServerId(), SearchCriteria.Op.EQ); DirectlyConnectedSearch.and("statuses", DirectlyConnectedSearch.entity().getStatus(), SearchCriteria.Op.EQ); + DirectlyConnectedSearch.and("resourceState", DirectlyConnectedSearch.entity().getResourceState(), SearchCriteria.Op.NOTIN); DirectlyConnectedSearch.done(); UnmanagedDirectConnectSearch = createSearchBuilder(); UnmanagedDirectConnectSearch.and("resource", UnmanagedDirectConnectSearch.entity().getResource(), SearchCriteria.Op.NNULL); UnmanagedDirectConnectSearch.and("server", UnmanagedDirectConnectSearch.entity().getManagementServerId(), SearchCriteria.Op.NULL); UnmanagedDirectConnectSearch.and("lastPinged", UnmanagedDirectConnectSearch.entity().getLastPinged(), SearchCriteria.Op.LTEQ); - UnmanagedDirectConnectSearch.and("statuses", UnmanagedDirectConnectSearch.entity().getStatus(), SearchCriteria.Op.NIN); + UnmanagedDirectConnectSearch.and("resourceStates", UnmanagedDirectConnectSearch.entity().getResourceState(), SearchCriteria.Op.NIN); /* * UnmanagedDirectConnectSearch.op(SearchCriteria.Op.OR, "managementServerId", * UnmanagedDirectConnectSearch.entity().getManagementServerId(), SearchCriteria.Op.EQ); @@ -238,7 +250,6 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao UnmanagedDirectConnectSearch.done(); - DirectConnectSearch = createSearchBuilder(); DirectConnectSearch.and("resource", DirectConnectSearch.entity().getResource(), SearchCriteria.Op.NNULL); DirectConnectSearch.and("id", DirectConnectSearch.entity().getId(), SearchCriteria.Op.EQ); @@ -295,88 +306,29 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao _statusAttr = _allAttributes.get("status"); _msIdAttr = _allAttributes.get("managementServerId"); _pingTimeAttr = _allAttributes.get("lastPinged"); + _resourceStateAttr = _allAttributes.get("resourceState"); assert (_statusAttr != null && _msIdAttr != null && _pingTimeAttr != null) : "Couldn't find one of these attributes"; } @Override - public long countBy(long clusterId, Status... statuses) { + public long countBy(long clusterId, ResourceState... states) { SearchCriteria sc = MaintenanceCountSearch.create(); - sc.setParameters("status", (Object[]) statuses); + sc.setParameters("resourceState", (Object[]) states); sc.setParameters("cluster", clusterId); List hosts = listBy(sc); return hosts.size(); } - - @Override - public HostVO findSecondaryStorageHost(long dcId) { - SearchCriteria sc = TypeDcSearch.create(); - sc.setParameters("type", Host.Type.SecondaryStorage); - sc.setParameters("dc", dcId); - List storageHosts = listBy(sc); - if (storageHosts == null || storageHosts.size() < 1) { - return null; - } else { - Collections.shuffle(storageHosts); - return storageHosts.get(0); - } - } - - @Override - public List listSecondaryStorageHosts() { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.SecondaryStorage); - return search(sc, null); - } - - @Override - public List listSecondaryStorageHosts(long dataCenterId) { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dataCenterId); - sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.SecondaryStorage); - return search(sc, null); - - } - - @Override - public List listLocalSecondaryStorageHosts() { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.LocalSecondaryStorage); - return search(sc, null); - } - - @Override - public List listLocalSecondaryStorageHosts(long dataCenterId) { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dataCenterId); - sc.addAnd("type", SearchCriteria.Op.EQ, Host.Type.LocalSecondaryStorage); - return search(sc, null); - - } - - @Override - public List listAllSecondaryStorageHosts(long dataCenterId) { - SearchCriteria sc = createSearchCriteria(); - sc.addAnd("dataCenterId", SearchCriteria.Op.EQ, dataCenterId); - sc.addAnd("type", SearchCriteria.Op.IN, new Object[]{Host.Type.LocalSecondaryStorage, Host.Type.SecondaryStorage}); - return search(sc, null); - } - - @Override - public List findDirectlyConnectedHosts() { - SearchCriteria sc = DirectlyConnectedSearch.create(); - return search(sc, null); - } - + @Override @DB public List findAndUpdateDirectAgentToLoad(long lastPingSecondsAfter, Long limit, long managementServerId) { Transaction txn = Transaction.currentTxn(); txn.start(); SearchCriteria sc = UnmanagedDirectConnectSearch.create(); sc.setParameters("lastPinged", lastPingSecondsAfter); - sc.setParameters("statuses", Status.ErrorInMaintenance, Status.Maintenance, Status.PrepareForMaintenance); + //sc.setParameters("resourceStates", ResourceState.ErrorInMaintenance, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.Disabled); sc.setJoinParameters("ClusterManagedSearch", "managed", Managed.ManagedState.Managed); List hosts = lockRows(sc, new Filter(HostVO.class, "clusterId", true, 0L, limit), true); @@ -414,7 +366,6 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao public void markHostsAsDisconnected(long msId, long lastPing) { SearchCriteria sc = MsStatusSearch.create(); sc.setParameters("ms", msId); - sc.setParameters("statuses", Status.ErrorInMaintenance, Status.Maintenance, Status.PrepareForMaintenance); HostVO host = createForUpdate(); host.setLastPinged(lastPing); @@ -434,55 +385,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao ub = getUpdateBuilder(host); update(ub, sc, null); } - - @Override - public List listBy(Host.Type type, Long clusterId, Long podId, long dcId) { - SearchCriteria sc = TypePodDcStatusSearch.create(); - if (type != null) { - sc.setParameters("type", type.toString()); - } - if (clusterId != null) { - sc.setParameters("cluster", clusterId); - } - if (podId != null) { - sc.setParameters("pod", podId); - } - sc.setParameters("dc", dcId); - sc.setParameters("status", Status.Up.toString()); - - return listBy(sc); - } - - @Override - public List listByInAllStatus(Host.Type type, Long clusterId, Long podId, long dcId) { - SearchCriteria sc = TypePodDcStatusSearch.create(); - if ( type != null ) { - sc.setParameters("type", type.toString()); - } - if (clusterId != null) { - sc.setParameters("cluster", clusterId); - } - if (podId != null ) { - sc.setParameters("pod", podId); - } - sc.setParameters("dc", dcId); - - return listBy(sc); - } - - @Override - public List listBy(Long clusterId, Long podId, long dcId) { - SearchCriteria sc = TypePodDcStatusSearch.create(); - if (podId != null) { - sc.setParameters("pod", podId); - } - if (clusterId != null) { - sc.setParameters("cluster", clusterId); - } - sc.setParameters("dc", dcId); - return listBy(sc); - } - + @Override public List listByHostTag(Host.Type type, Long clusterId, Long podId, long dcId, String hostTag) { @@ -497,6 +400,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao hostSearch.and("dc", entity.getDataCenterId(), SearchCriteria.Op.EQ); hostSearch.and("cluster", entity.getClusterId(), SearchCriteria.Op.EQ); hostSearch.and("status", entity.getStatus(), SearchCriteria.Op.EQ); + hostSearch.and("resourceState", entity.getState(), SearchCriteria.Op.EQ); hostSearch.join("hostTagSearch", hostTagSearch, entity.getId(), tagEntity.getHostId(), JoinBuilder.JoinType.INNER); SearchCriteria sc = hostSearch.create(); @@ -510,68 +414,11 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao } sc.setParameters("dc", dcId); sc.setParameters("status", Status.Up.toString()); - - return listBy(sc); - } - - @Override - public List listByCluster(long clusterId) { - SearchCriteria sc = ClusterStatusSearch.create(); - - sc.setParameters("cluster", clusterId); + sc.setParameters("resourceState", ResourceState.Enabled.toString()); return listBy(sc); } - - @Override - public List listByClusterStatus(long clusterId, Status status) { - SearchCriteria sc = ClusterStatusSearch.create(); - - sc.setParameters("cluster", clusterId); - sc.setParameters("status", status.toString()); - - return listBy(sc); - } - - - @Override - public List listBy(Host.Type type, long dcId) { - SearchCriteria sc = TypeDcStatusSearch.create(); - sc.setParameters("type", type.toString()); - sc.setParameters("dc", dcId); - sc.setParameters("status", Status.Up.toString()); - - return listBy(sc); - } - - @Override - public List listAllBy(Host.Type type, long dcId) { - SearchCriteria sc = TypeDcSearch.create(); - sc.setParameters("type", type.toString()); - sc.setParameters("dc", dcId); - - return listBy(sc); - } - - @Override - public HostVO findByPrivateIpAddressInDataCenter(long dcId, String privateIpAddress) { - SearchCriteria sc = DcPrivateIpAddressSearch.create(); - sc.setParameters("dc", dcId); - sc.setParameters("privateIpAddress", privateIpAddress); - - return findOneBy(sc); - } - - @Override - public HostVO findByStorageIpAddressInDataCenter(long dcId, String privateIpAddress) { - SearchCriteria sc = DcStorageIpAddressSearch.create(); - sc.setParameters("dc", dcId); - sc.setParameters("storageIpAddress", privateIpAddress); - - return findOneBy(sc); - } - @Override public void loadDetails(HostVO host) { Map details = _detailsDao.findDetails(host.getId()); @@ -584,132 +431,6 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao host.setHostTags(hostTags); } - @Override - public boolean directConnect(HostVO host, long msId) { - SearchCriteria sc = DirectConnectSearch.create(); - sc.setParameters("id", host.getId()); - sc.setParameters("server", msId); - - host.setManagementServerId(msId); - host.setLastPinged(System.currentTimeMillis() >> 10); - UpdateBuilder ub = getUpdateBuilder(host); - ub.set(host, _statusAttr, Status.Connecting); - - return update(host, sc) > 0; - } - - @Override - public boolean updateStatus(HostVO host, Event event, long msId) { - if (host == null) { - return false; - } - - Status oldStatus = host.getStatus(); - long oldPingTime = host.getLastPinged(); - Status newStatus = oldStatus.getNextStatus(event); - - if (newStatus == null) { - return false; - } - - SearchBuilder sb = createSearchBuilder(); - sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ); - sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); - if (newStatus.checkManagementServer()) { - sb.and("ping", sb.entity().getLastPinged(), SearchCriteria.Op.EQ); - sb.and().op("nullmsid", sb.entity().getManagementServerId(), SearchCriteria.Op.NULL); - sb.or("msid", sb.entity().getManagementServerId(), SearchCriteria.Op.EQ); - sb.closeParen(); - } - sb.done(); - - SearchCriteria sc = sb.create(); - - sc.setParameters("status", oldStatus); - sc.setParameters("id", host.getId()); - if (newStatus.checkManagementServer()) { - sc.setParameters("ping", oldPingTime); - sc.setParameters("msid", msId); - } - - UpdateBuilder ub = getUpdateBuilder(host); - ub.set(host, _statusAttr, newStatus); - if (newStatus.updateManagementServer()) { - if (newStatus.lostConnection()) { - ub.set(host, _msIdAttr, null); - } else { - ub.set(host, _msIdAttr, msId); - } - if (event.equals(Event.Ping) || event.equals(Event.AgentConnected)) { - ub.set(host, _pingTimeAttr, System.currentTimeMillis() >> 10); - } - } - if (event.equals(Event.ManagementServerDown)) { - ub.set(host, _pingTimeAttr, ((System.currentTimeMillis() >> 10) - (10 * 60))); - } - int result = update(ub, sc, null); - - assert result <= 1 : "How can this update " + result + " rows? "; - if (result < 1) { - s_logger.warn("Unable to update db record for host id=" + host.getId() + "; it's possible that the host is removed"); - } - - if (s_logger.isDebugEnabled() && result == 0) { - HostVO vo = findById(host.getId()); - - if (vo != null) { - StringBuilder str = new StringBuilder("Unable to update host for event:").append(event.toString()); - str.append(". New=[status=").append(newStatus.toString()).append(":msid=").append(newStatus.lostConnection() ? "null" : msId).append(":lastpinged=").append(host.getLastPinged()) - .append("]"); - str.append("; Old=[status=").append(oldStatus.toString()).append(":msid=").append(msId).append(":lastpinged=").append(oldPingTime).append("]"); - str.append("; DB=[status=").append(vo.getStatus().toString()).append(":msid=").append(vo.getManagementServerId()).append(":lastpinged=").append(vo.getLastPinged()).append("]"); - s_logger.debug(str.toString()); - } else { - s_logger.warn("Can't find host db record by id=" + host.getId() + "; host might be already marked as removed"); - } - - } - return result > 0; - - } - - @Override - public boolean disconnect(HostVO host, Event event, long msId) { - host.setDisconnectedOn(new Date()); - if (event != null && event.equals(Event.Remove)) { - host.setGuid(null); - host.setClusterId(null); - } - return updateStatus(host, event, msId); - } - - @Override - @DB - public boolean connect(HostVO host, long msId) { - Transaction txn = Transaction.currentTxn(); - long id = host.getId(); - txn.start(); - - if (!updateStatus(host, Event.AgentConnected, msId)) { - return false; - } - - txn.commit(); - return true; - } - - @Override - public HostVO findByGuid(String guid) { - SearchCriteria sc = GuidSearch.create("guid", guid); - return findOneBy(sc); - } - - @Override - public HostVO findByName(String name) { - SearchCriteria sc = NameSearch.create("name", name); - return findOneBy(sc); - } - @DB @Override public List findLostHosts(long timeout) { @@ -741,75 +462,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao } return result; } - - @Override - public List findHostsLike(String hostName) { - SearchCriteria sc = NameLikeSearch.create(); - sc.setParameters("name", "%" + hostName + "%"); - return listBy(sc); - } - - - - @Override - public List listByDataCenter(long dcId) { - SearchCriteria sc = DcSearch.create("dc", dcId); - return listBy(sc); - } - - @Override - public HostVO findConsoleProxyHost(String name, Type type) { - SearchCriteria sc = ConsoleProxyHostSearch.create(); - sc.setParameters("name", name); - sc.setParameters("type", type); - List hostList = listBy(sc); - - if (hostList == null || hostList.size() == 0) { - return null; - } else { - return hostList.get(0); - } - } - - @Override - public List listByHostPod(long podId) { - SearchCriteria sc = PodSearch.create("pod", podId); - return listBy(sc); - } - - @Override - public List listByStatus(Status... status) { - SearchCriteria sc = StatusSearch.create(); - sc.setParameters("status", (Object[]) status); - return listBy(sc); - } - - @Override - public List listByTypeDataCenter(Type type, long dcId) { - SearchCriteria sc = TypeDcSearch.create(); - sc.setParameters("type", type.toString()); - sc.setParameters("dc", dcId); - - return listBy(sc); - } - - @Override - public List listSecondaryStorageVM(long dcId) { - SearchCriteria sc = SecondaryStorageVMSearch.create(); - sc.setParameters("type", Type.SecondaryStorageVM); - sc.setParameters("status", Status.Up); - sc.setParameters("dc", dcId); - - return listBy(sc); - } - - @Override - public List listByType(Type type) { - SearchCriteria sc = TypeSearch.create(); - sc.setParameters("type", type.toString()); - return listBy(sc); - } - + @Override public void saveDetails(HostVO host) { Map details = host.getDetails(); @@ -920,48 +573,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao return s_seqFetcher.getNextSequence(Long.class, tg, hostId); } - @Override - public List getAvailHypervisorInZone(Long hostId, Long zoneId) { - SearchCriteria sc = AvailHypevisorInZone.create(); - if ( zoneId != null ) { - sc.setParameters("zoneId", zoneId); - } - if ( hostId != null ) { - sc.setParameters("hostId", hostId); - } - sc.setParameters("type", Host.Type.Routing); - List hosts = listBy(sc); - List hypers = new ArrayList(4); - for (HostVO host : hosts) { - hypers.add(host.getHypervisorType()); - } - return hypers; - } - - @Override - public List listBy(Long dataCenterId, Long podId, Long clusterId, Type hostType, Status... statuses) { - SearchCriteria sc = HostsInStatusSearch.create(); - if (dataCenterId != null) { - sc.setParameters("dc", dataCenterId); - } - - if (podId != null) { - sc.setParameters("pod", podId); - } - - if (clusterId != null) { - sc.setParameters("cluster", clusterId); - } - - if (hostType != null) { - sc.setParameters("type", hostType); - } - - sc.setParameters("statuses", (Object[]) statuses); - - return customSearch(sc, null); - } - + /*TODO: this is used by mycloud, check if it needs resource state Enabled */ @Override public long countRoutingHostsByDataCenter(long dcId) { SearchCriteria sc = CountRoutingByDc.create(); @@ -971,57 +583,122 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao return customSearch(sc, null).get(0); } - @Override - public HostVO findTrafficMonitorHost() { - SearchCriteria sc = TypeSearch.create(); - sc.setParameters("type", Host.Type.TrafficMonitor); - List trafficHosts = listBy(sc); - if (trafficHosts == null || trafficHosts.size() < 1) { - return null; + @Override + public boolean updateState(Status oldStatus, Event event, Status newStatus, Host vo, Long id) { + HostVO host = (HostVO) vo; + long oldPingTime = host.getLastPinged(); + + SearchBuilder sb = createSearchBuilder(); + sb.and("status", sb.entity().getStatus(), SearchCriteria.Op.EQ); + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); + sb.and("update", sb.entity().getUpdated(), SearchCriteria.Op.EQ); + if (newStatus.checkManagementServer()) { + sb.and("ping", sb.entity().getLastPinged(), SearchCriteria.Op.EQ); + sb.and().op("nullmsid", sb.entity().getManagementServerId(), SearchCriteria.Op.NULL); + sb.or("msid", sb.entity().getManagementServerId(), SearchCriteria.Op.EQ); + sb.closeParen(); + } + sb.done(); + + SearchCriteria sc = sb.create(); + + sc.setParameters("status", oldStatus); + sc.setParameters("id", host.getId()); + sc.setParameters("update", host.getUpdated()); + long oldUpdateCount = host.getUpdated(); + if (newStatus.checkManagementServer()) { + sc.setParameters("ping", oldPingTime); + sc.setParameters("msid", host.getManagementServerId()); + } + + long newUpdateCount = host.incrUpdated(); + UpdateBuilder ub = getUpdateBuilder(host); + ub.set(host, _statusAttr, newStatus); + if (newStatus.updateManagementServer()) { + if (newStatus.lostConnection()) { + ub.set(host, _msIdAttr, null); + } else { + ub.set(host, _msIdAttr, host.getManagementServerId()); + } + if (event.equals(Event.Ping) || event.equals(Event.AgentConnected)) { + ub.set(host, _pingTimeAttr, System.currentTimeMillis() >> 10); + } + } + if (event.equals(Event.ManagementServerDown)) { + ub.set(host, _pingTimeAttr, ((System.currentTimeMillis() >> 10) - (10 * 60))); + } + int result = update(ub, sc, null); + assert result <= 1 : "How can this update " + result + " rows? "; + + if (status_logger.isDebugEnabled() && result == 0) { + HostVO ho = findById(host.getId()); + assert ho != null : "How how how? : " + host.getId(); + + StringBuilder str = new StringBuilder("Unable to update host for event:").append(event.toString()); + str.append(". Name=").append(host.getName()); + str.append("; New=[status=").append(newStatus.toString()).append(":msid=") + .append(newStatus.lostConnection() ? "null" : host.getManagementServerId()).append(":lastpinged=").append(host.getLastPinged()).append("]"); + str.append("; Old=[status=").append(oldStatus.toString()).append(":msid=").append(host.getManagementServerId()).append(":lastpinged=") + .append(oldPingTime).append("]"); + str.append("; DB=[status=").append(vo.getStatus().toString()).append(":msid=").append(vo.getManagementServerId()).append(":lastpinged=") + .append(vo.getLastPinged()).append(":old update count=").append(oldUpdateCount).append("]"); + status_logger.debug(str.toString()); + } else { + StringBuilder msg = new StringBuilder("Agent status update: ["); + msg.append("id = " + host.getId()); + msg.append("; name = " + host.getName()); + msg.append("; old status = " + oldStatus); + msg.append("; event = " + event); + msg.append("; new status = " + newStatus); + msg.append("; old update count = " + oldUpdateCount); + msg.append("; new update count = " + newUpdateCount + "]"); + status_logger.debug(msg.toString()); + } + + 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("resource_state", oldState); + sc.setParameters("id", host.getId()); + + UpdateBuilder ub = getUpdateBuilder(host); + ub.set(host, _resourceStateAttr, newState); + int result = update(ub, sc, null); + assert result <= 1 : "How can this update " + result + " rows? "; + + if (state_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: ["); + str.append("m = " + host.getId()); + str.append("; name = " + host.getName()); + str.append("; old state = " + oldState); + str.append("; event = " + event); + str.append("; new state = " + newState + "]"); + state_logger.debug(str.toString()); } else { - return trafficHosts.get(0); + StringBuilder msg = new StringBuilder("Resource state update: ["); + msg.append("id = " + host.getId()); + msg.append("; name = " + host.getName()); + msg.append("; old state = " + oldState); + msg.append("; event = " + event); + msg.append("; new state = " + newState + "]"); + state_logger.debug(msg.toString()); } - } - - @Override - public List listDirectHostsBy(long msId, Status status) { - SearchCriteria sc = DirectlyConnectedSearch.create(); - sc.setParameters("ms", msId); - if (status != null) { - sc.setParameters("statuses", Status.Up); - } - - return listBy(sc); - } - - @Override - public List listManagedDirectAgents() { - SearchCriteria sc = ManagedDirectConnectSearch.create(); - return listBy(sc); - } - - @Override - public List listManagedRoutingAgents() { - SearchCriteria sc = ManagedRoutingServersSearch.create(); - sc.setParameters("type", Type.Routing); - return listBy(sc); - } - - @Override - public List listRoutingHostsByManagementServer(long msId) { - SearchCriteria sc = MsStatusSearch.create(); - sc.setParameters("ms", msId); - sc.setParameters("type", Type.Routing); - - return listBy(sc); - } - - @Override - public List listAllRoutingAgents() { - SearchCriteria sc = RoutingSearch.create(); - sc.setParameters("type", Type.Routing); - return listBy(sc); + + return result > 0; } } diff --git a/server/src/com/cloud/hypervisor/CloudZonesStartupProcessor.java b/server/src/com/cloud/hypervisor/CloudZonesStartupProcessor.java old mode 100644 new mode 100755 index b8161a3a5a0..28d383b1c22 --- a/server/src/com/cloud/hypervisor/CloudZonesStartupProcessor.java +++ b/server/src/com/cloud/hypervisor/CloudZonesStartupProcessor.java @@ -134,6 +134,7 @@ public class CloudZonesStartupProcessor implements StartupCommandProcessor { } protected boolean processHostStartup(StartupRoutingCommand startup) throws ConnectionException{ + /* boolean found = false; Type type = Host.Type.Routing; final Map hostDetails = startup.getHostDetails(); @@ -170,6 +171,7 @@ public class CloudZonesStartupProcessor implements StartupCommandProcessor { s_logger.info("Old " + server.getType().toString() + " host reconnected w/ id =" + server.getId()); } + */ return true; @@ -396,6 +398,7 @@ public class CloudZonesStartupProcessor implements StartupCommandProcessor { protected boolean processStorageStartup(StartupStorageCommand startup) throws ConnectionException{ + /* if (startup.getResourceType() != Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE) { return false; } @@ -435,6 +438,7 @@ public class CloudZonesStartupProcessor implements StartupCommandProcessor { s_logger.info("Old " + server.getType().toString() + " host reconnected w/ id =" + server.getId()); } + */ return true; diff --git a/server/src/com/cloud/hypervisor/hyperv/HypervServerDiscoverer.java b/server/src/com/cloud/hypervisor/hyperv/HypervServerDiscoverer.java index 4369deea3f9..5c830e7c340 100755 --- a/server/src/com/cloud/hypervisor/hyperv/HypervServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/hyperv/HypervServerDiscoverer.java @@ -48,6 +48,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.hyperv.resource.HypervDummyResourceBase; import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; +import com.cloud.resource.ResourceManager; import com.cloud.resource.ServerResource; import com.cloud.utils.component.Inject; import com.cloud.utils.nio.HandlerFactory; @@ -65,6 +66,7 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer @Inject AlertManager _alertMgr; @Inject ClusterDetailsDao _clusterDetailsDao; @Inject HostDao _hostDao = null; + @Inject ResourceManager _resourceMgr; Link _link; @SuppressWarnings("static-access") @@ -105,7 +107,7 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer String agentIp = ia.getHostAddress(); String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString(); String guidWithTail = guid + "-HypervResource";/*tail added by agent.java*/ - if (_hostDao.findByGuid(guidWithTail) != null) { + if (_resourceMgr.findHostByGuid(guidWithTail) != null) { s_logger.debug("Skipping " + agentIp + " because " + guidWithTail + " is already in the database."); return null; } @@ -204,7 +206,7 @@ public class HypervServerDiscoverer extends DiscovererBase implements Discoverer private HostVO waitForHostConnect(long dcId, long podId, long clusterId, String guid) { for (int i = 0; i < _waitTime *2; i++) { - List hosts = _hostDao.listBy(Host.Type.Routing, clusterId, podId, dcId); + List hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId); for (HostVO host : hosts) { if (host.getGuid().equalsIgnoreCase(guid)) { return host; diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java index 289d215d20f..86f3946c94a 100755 --- a/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/kvm/discoverer/KvmServerDiscoverer.java @@ -30,18 +30,23 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +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.ShutdownCommand; import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterVO; import com.cloud.dc.dao.ClusterDao; +import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.DiscoveredWithErrorException; import com.cloud.exception.DiscoveryException; +import com.cloud.exception.OperationTimedoutException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; @@ -51,7 +56,10 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.kvm.resource.KvmDummyResourceBase; import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.utils.script.Script; @@ -62,7 +70,7 @@ import com.trilead.ssh2.Session; @Local(value=Discoverer.class) public class KvmServerDiscoverer extends DiscovererBase implements Discoverer, - Listener { + Listener, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(KvmServerDiscoverer.class); private String _setupAgentPath; private ConfigurationDao _configDao; @@ -73,6 +81,8 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer, private String _kvmGuestNic; @Inject HostDao _hostDao = null; @Inject ClusterDao _clusterDao; + @Inject ResourceManager _resourceMgr; + @Inject AgentManager _agentMgr; @Override public boolean processAnswers(long agentId, long seq, Answer[] answers) { @@ -149,7 +159,7 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer, agentIp = ia.getHostAddress(); String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString(); String guidWithTail = guid + "-LibvirtComputingResource";/*tail added by agent.java*/ - if (_hostDao.findByGuid(guidWithTail) != null) { + if (_resourceMgr.findHostByGuid(guidWithTail) != null) { s_logger.debug("Skipping " + agentIp + " because " + guidWithTail + " is already in the database."); return null; } @@ -221,7 +231,7 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer, private HostVO waitForHostConnect(long dcId, long podId, long clusterId, String guid) { for (int i = 0; i < _waitTime *2; i++) { - List hosts = _hostDao.listBy(Host.Type.Routing, clusterId, podId, dcId); + List hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId); for (HostVO host : hosts) { if (host.getGuid().equalsIgnoreCase(guid)) { return host; @@ -264,6 +274,7 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer, if (_hostIp == null) { throw new ConfigurationException("Can't get host IP"); } + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -289,5 +300,67 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer, return Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisor); } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + StartupCommand firstCmd = cmd[0]; + if (!(firstCmd instanceof StartupRoutingCommand)) { + return null; + } + + StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd); + if (ssCmd.getHypervisorType() != HypervisorType.KVM) { + return null; + } + + /* KVM requires host are the same in cluster */ + ClusterVO clusterVO = _clusterDao.findById(host.getClusterId()); + List hostsInCluster = _resourceMgr.listAllHostsInCluster(clusterVO.getId()); + if (!hostsInCluster.isEmpty()) { + HostVO oneHost = hostsInCluster.get(0); + _hostDao.loadDetails(oneHost); + String hostOsInCluster = oneHost.getDetail("Host.OS"); + String hostOs = ssCmd.getHostDetails().get("Host.OS"); + if (!hostOsInCluster.equalsIgnoreCase(hostOs)) { + throw new IllegalArgumentException("Can't add host: " + firstCmd.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster," + + "in which there are " + hostOsInCluster + " hosts added"); + } + } + + return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.KVM, null, null); + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + // TODO Auto-generated method stub + return null; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + if (host.getType() != Host.Type.Routing || host.getHypervisorType() != HypervisorType.KVM) { + return null; + } + + _resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage); + try { + ShutdownCommand cmd = new ShutdownCommand(ShutdownCommand.DeleteHost, null); + _agentMgr.send(host.getId(), cmd); + } catch (AgentUnavailableException e) { + s_logger.warn("Sending ShutdownCommand failed: ", e); + } catch (OperationTimedoutException e) { + s_logger.warn("Sending ShutdownCommand failed: ", e); + } + + return new DeleteHostAnswer(true); + } + + @Override + public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); + return super.stop(); + } + } diff --git a/server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java b/server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java index 88b56a2a2c6..c9f54f40549 100755 --- a/server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java +++ b/server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java @@ -62,6 +62,7 @@ import com.cloud.org.Cluster.ClusterType; import com.cloud.secstorage.CommandExecLogDao; import com.cloud.serializer.GsonHelper; import com.cloud.storage.StorageLayer; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.utils.FileUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -102,6 +103,7 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis @Inject ClusterManager _clusterMgr; @Inject CheckPointManager _checkPointMgr; @Inject VirtualNetworkApplianceManager _routerMgr; + @Inject SecondaryStorageVmManager _ssvmMgr; String _mountParent; StorageLayer _storage; @@ -436,7 +438,7 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis @Override public String getSecondaryStorageStoreUrl(long dcId) { - List secStorageHosts = _hostDao.listSecondaryStorageHosts(dcId); + List secStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); if(secStorageHosts.size() > 0) return secStorageHosts.get(0).getStorageUrl(); diff --git a/server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java b/server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java index 2b692ee571c..8c29de6ce3c 100755 --- a/server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java @@ -16,6 +16,8 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.alert.AlertManager; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterDetailsDao; @@ -35,7 +37,10 @@ import com.cloud.hypervisor.vmware.resource.VmwareResource; import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.VMTemplateVO; @@ -48,7 +53,7 @@ import com.vmware.vim25.ClusterDasConfigInfo; import com.vmware.vim25.ManagedObjectReference; @Local(value=Discoverer.class) -public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer { +public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(VmwareServerDiscoverer.class); @Inject ClusterDao _clusterDao; @@ -57,6 +62,7 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer @Inject VMTemplateDao _tmpltDao; @Inject ClusterDetailsDao _clusterDetailsDao; @Inject HostDao _hostDao; + @Inject ResourceManager _resourceMgr; @Override public Map> find(long dcId, Long podId, Long clusterId, URI url, @@ -78,7 +84,7 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer return null; } - List hosts = _hostDao.listByCluster(clusterId); + List hosts = _resourceMgr.listAllHostsInCluster(clusterId); if(hosts.size() >= _vmwareMgr.getMaxHostsPerCluster()) { String msg = "VMware cluster " + cluster.getName() + " is too big to add new host now. (current configured cluster size: " + _vmwareMgr.getMaxHostsPerCluster() + ")"; s_logger.error(msg); @@ -224,8 +230,10 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer createVmwareToolsIso(); - if(s_logger.isInfoEnabled()) - s_logger.info("VmwareServerDiscoverer has been successfully configured"); + if(s_logger.isInfoEnabled()) { + s_logger.info("VmwareServerDiscoverer has been successfully configured"); + } + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -245,6 +253,40 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer tmplt.setUrl(null); _tmpltDao.update(id, tmplt); } + } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupRoutingCommand)) { + return null; + } + + StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd); + if (ssCmd.getHypervisorType() != HypervisorType.VMware) { + return null; + } + + return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.VMware, details, hostTags); + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); + return super.stop(); } } diff --git a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java index 27cd6bc7d14..ffc1bc24075 100755 --- a/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java @@ -47,7 +47,11 @@ import com.cloud.alert.AlertManager; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.HostPodVO; import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConnectionException; import com.cloud.exception.DiscoveredWithErrorException; @@ -69,7 +73,10 @@ import com.cloud.hypervisor.xen.resource.XenServer600Resource; import com.cloud.hypervisor.xen.resource.XenServerConnectionPool; import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.VMTemplateVO; @@ -88,7 +95,7 @@ import com.xensource.xenapi.Types.SessionAuthenticationFailed; import com.xensource.xenapi.Types.XenAPIException; @Local(value=Discoverer.class) -public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, Listener { +public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(XcpServerDiscoverer.class); protected String _publicNic; protected String _privateNic; @@ -108,6 +115,9 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L @Inject VMTemplateHostDao _vmTemplateHostDao; @Inject ClusterDao _clusterDao; @Inject protected ConfigurationDao _configDao; + @Inject ResourceManager _resourceMgr; + @Inject HostPodDao _podDao; + @Inject DataCenterDao _dcDao; protected XcpServerDiscoverer() { } @@ -141,7 +151,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L } try { - List eHosts = _hostDao.listByCluster(clusterId); + List eHosts = _resourceMgr.listAllHostsInCluster(clusterId); if( eHosts.size() > 0 ) { HostVO eHost = eHosts.get(0); _hostDao.loadDetails(eHost); @@ -170,7 +180,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if ( clu.getGuid()== null ) { clu.setGuid(poolUuid); } else { - List clusterHosts = _hostDao.listByCluster(clusterId); + List clusterHosts = _resourceMgr.listAllHostsInCluster(clusterId); if( clusterHosts != null && clusterHosts.size() > 0) { if (!clu.getGuid().equals(poolUuid)) { if (hosts.size() == 1) { @@ -233,7 +243,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L String hostOSVer = prodVersion; String hostKernelVer = record.softwareVersion.get("linux"); - if (_hostDao.findByGuid(record.uuid) != null) { + if (_resourceMgr.findHostByGuid(record.uuid) != null) { s_logger.debug("Skipping " + record.address + " because " + record.uuid + " is already in the database."); continue; } @@ -338,7 +348,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L protected boolean addHostsToPool(Connection conn, String hostIp, Long clusterId) throws XenAPIException, XmlRpcException, DiscoveryException { List hosts; - hosts = _hostDao.listByCluster(clusterId); + hosts = _resourceMgr.listAllHostsInCluster(clusterId); String masterIp = null; String username = null; @@ -454,6 +464,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L _agentMgr.registerForHostEvents(this, true, false, true); createXsToolsISO(); + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -617,5 +628,43 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L @Override public boolean processTimeout(long agentId, long seq) { return false; - } + } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupRoutingCommand)) { + return null; + } + + StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd); + if (ssCmd.getHypervisorType() != HypervisorType.XenServer) { + return null; + } + + HostPodVO pod = _podDao.findById(host.getPodId()); + DataCenterVO dc = _dcDao.findById(host.getDataCenterId()); + s_logger.info("Host: " + host.getName() + " connected with hypervisor type: " + HypervisorType.XenServer + ". Checking CIDR..."); + _resourceMgr.checkCIDR(pod, dc, ssCmd.getPrivateIpAddress(), ssCmd.getPrivateNetmask()); + return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.XenServer, details, hostTags); + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); + return super.stop(); + } } diff --git a/server/src/com/cloud/migration/Db21to22MigrationUtil.java b/server/src/com/cloud/migration/Db21to22MigrationUtil.java old mode 100644 new mode 100755 index 906ecaa58a3..a66840e120c --- a/server/src/com/cloud/migration/Db21to22MigrationUtil.java +++ b/server/src/com/cloud/migration/Db21to22MigrationUtil.java @@ -43,6 +43,7 @@ import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.xen.resource.XenServerConnectionPool; +import com.cloud.resource.ResourceManager; import com.cloud.user.Account; import com.cloud.user.dao.AccountDao; import com.cloud.utils.PropertiesUtil; @@ -68,6 +69,7 @@ public class Db21to22MigrationUtil { private InstanceGroupVMMapDao _groupVMMapDao; private ConfigurationDao _configurationDao; private DataCenterDao _zoneDao; + private ResourceManager _resourceMgr; private void doMigration() { setupComponents(); @@ -88,7 +90,7 @@ public class Db21to22MigrationUtil { XenServerConnectionPool _connPool = XenServerConnectionPool.getInstance(); List clusters = _clusterDao.listByHyTypeWithoutGuid(HypervisorType.XenServer.toString()); for (ClusterVO cluster : clusters) { - List hosts = _hostDao.listByCluster(cluster.getId()); + List hosts = _resourceMgr.listAllHostsInCluster(cluster.getId()); for (HostVO host : hosts) { String ip = host.getPrivateIpAddress(); String username = host.getDetail("username"); @@ -179,6 +181,7 @@ public class Db21to22MigrationUtil { _groupVMMapDao = locator.getDao(InstanceGroupVMMapDao.class); _configurationDao = locator.getDao(ConfigurationDao.class); _zoneDao = locator.getDao(DataCenterDao.class); + _resourceMgr = locator.getManager(ResourceManager.class); } private void setupInstanceGroups() { diff --git a/server/src/com/cloud/network/ExternalNetworkManagerImpl.java b/server/src/com/cloud/network/ExternalNetworkManagerImpl.java old mode 100644 new mode 100755 index 64d6b3f122e..862bf64bf1d --- a/server/src/com/cloud/network/ExternalNetworkManagerImpl.java +++ b/server/src/com/cloud/network/ExternalNetworkManagerImpl.java @@ -37,6 +37,9 @@ import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; import com.cloud.agent.api.ExternalNetworkResourceUsageCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupExternalFirewallCommand; +import com.cloud.agent.api.StartupExternalLoadBalancerCommand; import com.cloud.agent.api.routing.IpAssocCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; import com.cloud.agent.api.routing.NetworkElementCommand; @@ -93,7 +96,10 @@ 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.ResourceStateAdapter; import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.server.api.response.ExternalFirewallResponse; import com.cloud.server.api.response.ExternalLoadBalancerResponse; import com.cloud.user.Account; @@ -121,7 +127,7 @@ import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; @Local(value = {ExternalNetworkManager.class}) -public class ExternalNetworkManagerImpl implements ExternalNetworkManager { +public class ExternalNetworkManagerImpl implements ExternalNetworkManager, ResourceStateAdapter { public enum ExternalNetworkResourceName { JuniperSrx, F5BigIp, @@ -147,6 +153,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { @Inject VpnUserDao _vpnUsersDao; @Inject InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao; @Inject AccountManager _accountMgr; + @Inject ResourceManager _resourceMgr; ScheduledExecutorService _executor; int _externalNetworkStatsInterval; @@ -161,6 +168,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { if (_externalNetworkStatsInterval > 0){ _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ExternalNetworkMonitor")); } + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -174,6 +182,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { @Override public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); return true; } @@ -192,7 +201,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { s_logger.debug("Zone " + zone.getName() + " is not configured for external networking."); return null; } else { - List externalNetworkAppliancesInZone = _hostDao.listBy(type, zoneId); + List externalNetworkAppliancesInZone = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(type, zoneId); if (externalNetworkAppliancesInZone.size() != 1) { return null; } else { @@ -216,7 +225,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { zoneName = zone.getName(); } - List externalLoadBalancersInZone = _hostDao.listByTypeDataCenter(Host.Type.ExternalLoadBalancer, zoneId); + List externalLoadBalancersInZone = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.ExternalLoadBalancer, zoneId); if (externalLoadBalancersInZone.size() != 0) { throw new InvalidParameterValueException("Already found an external load balancer in zone: " + zoneName); } @@ -285,7 +294,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()); @@ -309,7 +318,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { } try { - if (_agentMgr.maintain(hostId) && _agentMgr.deleteHost(hostId, false, false, caller)) { + if (_resourceMgr.maintain(hostId) && _resourceMgr.deleteHost(hostId, false, false)) { DataCenterVO zone = _dcDao.findById(externalLoadBalancer.getDataCenterId()); if (zone.getNetworkType().equals(NetworkType.Advanced)) { @@ -331,7 +340,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { @Override public List listExternalLoadBalancers(ListExternalLoadBalancersCmd cmd) { long zoneId = cmd.getZoneId(); - return _hostDao.listByTypeDataCenter(Host.Type.ExternalLoadBalancer, zoneId); + return _resourceMgr.listAllHostsInOneZoneByType(Host.Type.ExternalLoadBalancer, zoneId); } @Override @@ -533,7 +542,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { zoneName = zone.getName(); } - List externalFirewallsInZone = _hostDao.listByTypeDataCenter(Host.Type.ExternalFirewall, zoneId); + List externalFirewallsInZone = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.ExternalFirewall, zoneId); if (externalFirewallsInZone.size() != 0) { throw new InvalidParameterValueException("Already added an external firewall in zone: " + zoneName); } @@ -630,7 +639,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()); @@ -669,7 +678,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { } try { - if (_agentMgr.maintain(hostId) && _agentMgr.deleteHost(hostId, false, false, caller)) { + if (_resourceMgr.maintain(hostId) && _resourceMgr.deleteHost(hostId, false, false)) { DataCenterVO zone = _dcDao.findById(externalFirewall.getDataCenterId()); zone.setFirewallProvider(Network.Provider.VirtualRouter.getName()); zone.setUserDataProvider(Network.Provider.VirtualRouter.getName()); @@ -708,7 +717,7 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { @Override public List listExternalFirewalls(ListExternalFirewallsCmd cmd) { long zoneId = cmd.getZoneId(); - return _hostDao.listByTypeDataCenter(Host.Type.ExternalFirewall, zoneId); + return _resourceMgr.listAllHostsInOneZoneByType(Host.Type.ExternalFirewall, zoneId); } @Override @@ -1285,4 +1294,30 @@ public class ExternalNetworkManagerImpl implements ExternalNetworkManager { } } } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + if (startup[0] instanceof StartupExternalFirewallCommand) { + host.setType(Host.Type.ExternalFirewall); + return host; + } else if (startup[0] instanceof StartupExternalLoadBalancerCommand) { + host.setType(Host.Type.ExternalLoadBalancer); + return host; + } else { + return null; + } + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } } diff --git a/server/src/com/cloud/network/NetworkDeviceManagerImpl.java b/server/src/com/cloud/network/NetworkDeviceManagerImpl.java old mode 100644 new mode 100755 index 222c6f2f3a6..5027ccb486c --- a/server/src/com/cloud/network/NetworkDeviceManagerImpl.java +++ b/server/src/com/cloud/network/NetworkDeviceManagerImpl.java @@ -25,6 +25,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceManager; import com.cloud.server.api.response.NetworkDeviceResponse; import com.cloud.server.api.response.NwDeviceDhcpResponse; import com.cloud.server.api.response.PxePingResponse; @@ -38,6 +39,7 @@ public class NetworkDeviceManagerImpl implements NetworkDeviceManager { @Inject ExternalDhcpManager _dhcpMgr; @Inject PxeServerManager _pxeMgr; @Inject HostDao _hostDao; + @Inject ResourceManager _resourceMgr; @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -137,14 +139,14 @@ public class NetworkDeviceManagerImpl implements NetworkDeviceManager { private List listNetworkDevice(Long zoneId, Long podId, Host.Type type) { List res = new ArrayList(); if (podId != null) { - List devs = _hostDao.listBy(type, null, podId, zoneId); + List devs = _resourceMgr.listAllUpAndEnabledHosts(type, null, podId, zoneId); if (devs.size() == 1) { res.add(devs.get(0)); } else { s_logger.debug("List " + type + ": " + devs.size() + " found"); } } else { - List devs = _hostDao.listBy(type, zoneId); + List devs = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(type, zoneId); res.addAll(devs); } diff --git a/server/src/com/cloud/network/NetworkUsageManagerImpl.java b/server/src/com/cloud/network/NetworkUsageManagerImpl.java old mode 100644 new mode 100755 index d2a98f4caf5..3997c64a1ce --- a/server/src/com/cloud/network/NetworkUsageManagerImpl.java +++ b/server/src/com/cloud/network/NetworkUsageManagerImpl.java @@ -66,6 +66,10 @@ 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.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.server.api.response.TrafficMonitorResponse; import com.cloud.usage.UsageIPAddressVO; import com.cloud.user.AccountManager; @@ -87,7 +91,7 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.MacAddress; @Local(value = {NetworkUsageManager.class}) -public class NetworkUsageManagerImpl implements NetworkUsageManager { +public class NetworkUsageManagerImpl implements NetworkUsageManager, ResourceStateAdapter { public enum NetworkUsageResourceName { TrafficSentinel; } @@ -104,6 +108,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 AllocatedIpSearch; @@ -122,7 +127,7 @@ public class NetworkUsageManagerImpl implements NetworkUsageManager { } - List trafficMonitorsInZone = _hostDao.listByTypeDataCenter(Host.Type.TrafficMonitor, zoneId); + List trafficMonitorsInZone = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.TrafficMonitor, zoneId); if (trafficMonitorsInZone.size() != 0) { throw new InvalidParameterValueException("Already added an traffic monitor in zone: " + zoneName); } @@ -161,7 +166,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; } @@ -178,9 +183,9 @@ public class NetworkUsageManagerImpl implements NetworkUsageManager { throw new InvalidParameterValueException("Could not find an traffic monitor with ID: " + hostId); } - try { - if (_agentMgr.maintain(hostId) && _agentMgr.deleteHost(hostId, false, false, caller)) { - return true; + try { + if (_resourceMgr.maintain(hostId) && _resourceMgr.deleteHost(hostId, false, false)) { + return true; } else { return false; } @@ -193,7 +198,7 @@ public class NetworkUsageManagerImpl implements NetworkUsageManager { @Override public List listTrafficMonitors(ListTrafficMonitorsCmd cmd) { long zoneId = cmd.getZoneId(); - return _hostDao.listByTypeDataCenter(Host.Type.TrafficMonitor, zoneId); + return _resourceMgr.listAllHostsInOneZoneByType(Host.Type.TrafficMonitor, zoneId); } @Override @@ -221,6 +226,7 @@ public class NetworkUsageManagerImpl implements NetworkUsageManager { _networkStatsInterval = NumbersUtil.parseInt(_configDao.getValue(Config.DirectNetworkStatsInterval.key()), 86400); _agentMgr.registerForHostEvents(new DirectNetworkStatsListener( _networkStatsInterval), true, false, false); + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -231,6 +237,7 @@ public class NetworkUsageManagerImpl implements NetworkUsageManager { @Override public boolean stop() { + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); return true; } @@ -499,4 +506,27 @@ public class NetworkUsageManagerImpl implements NetworkUsageManager { } + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + if (!(startup[0] instanceof StartupTrafficMonitorCommand)) { + return null; + } + + host.setType(Host.Type.TrafficMonitor); + return host; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + // TODO Auto-generated method stub + return null; + } + } diff --git a/server/src/com/cloud/network/ovs/OvsListener.java b/server/src/com/cloud/network/ovs/OvsListener.java index 3e05c35f1f8..9fcbdad96b1 100755 --- a/server/src/com/cloud/network/ovs/OvsListener.java +++ b/server/src/com/cloud/network/ovs/OvsListener.java @@ -44,6 +44,8 @@ import com.cloud.network.ovs.dao.OvsWorkDao; import com.cloud.network.ovs.dao.OvsWorkVO.Step; import com.cloud.network.ovs.dao.VlanMappingDao; import com.cloud.network.ovs.dao.VlanMappingVO; +import com.cloud.resource.ResourceManager; +import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; public class OvsListener implements Listener { @@ -53,6 +55,7 @@ public class OvsListener implements Listener { GreTunnelDao _tunnelDao; VlanMappingDao _mappingDao; HostDao _hostDao; + ResourceManager _resourceMgr; public OvsListener(OvsNetworkManager ovsMgr, OvsWorkDao workDao, GreTunnelDao tunnelDao, VlanMappingDao mappingDao, HostDao hostDao) { @@ -61,6 +64,8 @@ public class OvsListener implements Listener { this._tunnelDao = tunnelDao; this._mappingDao = mappingDao; this._hostDao = hostDao; + ComponentLocator locator = ComponentLocator.getLocator("management-server"); + _resourceMgr = locator.getManager(ResourceManager.class); } @Override @@ -131,7 +136,7 @@ public class OvsListener implements Listener { } try { - List hosts = _hostDao.listByType(Host.Type.Routing); + List hosts = _resourceMgr.listAllHostsInAllZonesByType(Host.Type.Routing); for (HostVO h : hosts) { if (h.getId() == host.getId()) { continue; diff --git a/server/src/com/cloud/network/ovs/OvsTunnelListener.java b/server/src/com/cloud/network/ovs/OvsTunnelListener.java index 92093cad0d5..5d17a8cedc4 100755 --- a/server/src/com/cloud/network/ovs/OvsTunnelListener.java +++ b/server/src/com/cloud/network/ovs/OvsTunnelListener.java @@ -38,15 +38,20 @@ import com.cloud.host.dao.HostDao; import com.cloud.network.ovs.dao.GreTunnelVO; import com.cloud.network.ovs.dao.OvsTunnelDao; import com.cloud.network.ovs.dao.OvsTunnelVO; +import com.cloud.resource.ResourceManager; +import com.cloud.utils.component.ComponentLocator; public class OvsTunnelListener implements Listener { public static final Logger s_logger = Logger.getLogger(OvsListener.class.getName()); HostDao _hostDao; OvsTunnelDao _tunnelDao; + ResourceManager _resourceMgr; public OvsTunnelListener(OvsTunnelDao tunnelDao, HostDao hostDao) { this._hostDao = hostDao; this._tunnelDao = tunnelDao; + ComponentLocator locator = ComponentLocator.getLocator("management-server"); + _resourceMgr = locator.getManager(ResourceManager.class); } @Override @@ -76,7 +81,7 @@ public class OvsTunnelListener implements Listener { } try { - List hosts = _hostDao.listByType(Host.Type.Routing); + List hosts = _resourceMgr.listAllHostsInAllZonesByType(Host.Type.Routing); for (HostVO h : hosts) { if (h.getId() == host.getId()) { continue; diff --git a/server/src/com/cloud/resource/ResourceManager.java b/server/src/com/cloud/resource/ResourceManager.java index 526c22bb642..eebf5dad67e 100755 --- a/server/src/com/cloud/resource/ResourceManager.java +++ b/server/src/com/cloud/resource/ResourceManager.java @@ -17,7 +17,21 @@ */ package com.cloud.resource; +import java.util.List; +import java.util.Map; + +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.HostPodVO; +import com.cloud.exception.AgentUnavailableException; import com.cloud.host.Host; +import com.cloud.host.Status; +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 @@ -34,4 +48,62 @@ public interface ResourceManager { public void registerResourceEvent(Integer event, ResourceListener listener); public void unregisterResourceEvent(ResourceListener listener); + + /** + * + * @param name of adapter + * @param adapter + * @param hates, a list of names which will be eliminated by this adapter. Especially for the case where + * can be only one adapter responds to an event, e.g. startupCommand + */ + public void registerResourceStateAdapter(String name, ResourceStateAdapter adapter); + + public void unregisterResourceStateAdapter(String name); + + public Host createHostAndAgent(Long hostId, ServerResource resource, Map details, boolean old, List hostTags, + boolean forRebalance); + + public Host addHost(long zoneId, ServerResource resource, Type hostType, Map hostDetails); + + public HostVO createHostVOForConnectedAgent(StartupCommand[] cmds); + + public void checkCIDR(HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask); + + public HostVO fillRoutingHostVO(HostVO host, StartupRoutingCommand ssCmd, HypervisorType hyType, Map details, List hostTags); + + public void deleteRoutingHost(HostVO host, boolean isForced, boolean forceDestroyStorage) throws UnableDeleteHostException; + + public boolean executeUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException; + + boolean resourceStateTransitTo(Host host, Event event, long msId) throws NoTransitionException; + + boolean umanageHost(long hostId); + + boolean maintenanceFailed(long hostId); + + public boolean maintain(final long hostId) throws AgentUnavailableException; + + public boolean deleteHost(long hostId, boolean isForced, boolean isForceDeleteStorage); + + public List findDirectlyConnectedHosts(); + + public List listAllUpAndEnabledHosts(Host.Type type, Long clusterId, Long podId, long dcId); + + public List listAllHostsInCluster(long clusterId); + + public List listHostsInClusterByStatus(long clusterId, Status status); + + public List listAllUpAndEnabledHostsInOneZoneByType(Host.Type type, long dcId); + + public List listAllHostsInOneZoneByType(Host.Type type, long dcId); + + public List listAllHostsInAllZonesByType(Type type); + + public List listAvailHypervisorInZone(Long hostId, Long zoneId); + + public HostVO findHostByGuid(String guid); + + public HostVO findHostByName(String name); + + public List listHostsByNameLike(String name); } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 106118d260e..30b7abfa68c 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -33,7 +33,15 @@ 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.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.UpdateHostPasswordCommand; import com.cloud.agent.manager.AgentAttache; +import com.cloud.agent.transport.Request; +import com.cloud.api.ApiConstants; import com.cloud.api.commands.AddClusterCmd; import com.cloud.api.commands.AddHostCmd; import com.cloud.api.commands.AddSecondaryStorageCmd; @@ -43,21 +51,29 @@ import com.cloud.api.commands.PrepareForMaintenanceCmd; import com.cloud.api.commands.ReconnectHostCmd; import com.cloud.api.commands.UpdateHostCmd; import com.cloud.api.commands.UpdateHostPasswordCmd; +import com.cloud.capacity.Capacity; +import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; +import com.cloud.cluster.ClusterManager; import com.cloud.cluster.ManagementServerNode; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenterIpAddressVO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.DataCenterIpAddressDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.exception.AgentUnavailableException; 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.DetailVO; 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; @@ -66,26 +82,46 @@ import com.cloud.host.dao.HostTagsDao; import com.cloud.hypervisor.Hypervisor; 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.org.Cluster; import com.cloud.org.Grouping; import com.cloud.org.Managed; +import com.cloud.resource.ResourceState.Event; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.StorageManager; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolHostVO; +import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.StoragePoolVO; +import com.cloud.storage.StorageService; import com.cloud.storage.dao.GuestOSCategoryDao; import com.cloud.storage.dao.StoragePoolDao; +import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.User; import com.cloud.user.UserContext; +import com.cloud.utils.Pair; import com.cloud.utils.UriUtils; import com.cloud.utils.component.Adapters; import com.cloud.utils.component.Inject; import com.cloud.utils.component.Manager; import com.cloud.utils.db.DB; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteriaService; 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; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.dao.VMInstanceDao; @Local({ ResourceManager.class, ResourceService.class }) public class ResourceManagerImpl implements ResourceManager, ResourceService, Manager { @@ -122,11 +158,34 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma protected GuestOSCategoryDao _guestOSCategoryDao; @Inject protected StoragePoolDao _storagePoolDao; - + @Inject + protected DataCenterIpAddressDao _privateIPAddressDao; + @Inject + protected IPAddressDao _publicIPAddressDao; + @Inject + protected VirtualMachineManager _vmMgr; + @Inject + protected VMInstanceDao _vmDao; + @Inject + protected HighAvailabilityManager _haMgr; + @Inject + protected StorageService _storageSvr; @Inject(adapter = Discoverer.class) protected Adapters _discoverers; + @Inject + protected ClusterManager _clusterMgr; + @Inject + protected StoragePoolHostDao _storagePoolHostDao; + @Inject + protected StoragePoolDao _storagePoolDao; + @Inject + protected CapacityDao _capacityDao; + @Inject + protected HostDetailsDao _detailsDao; protected long _nodeId = ManagementServerNode.getManagementServerId(); + + protected HashMap _resourceStateAdapters = new HashMap(); protected HashMap> _lifeCycleListeners = new HashMap>(); @@ -227,11 +286,6 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } - @Override - public boolean updateHostPassword(UpdateHostPasswordCmd cmd) { - return _agentMgr.updateHostPassword(cmd); - } - @Override public List discoverCluster(AddClusterCmd cmd) throws IllegalArgumentException, DiscoveryException { Long dcId = cmd.getZoneId(); @@ -367,9 +421,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, false); + if (host != null) { + hosts.add(host); } discoverer.postDiscovery(hosts, _nodeId); } @@ -423,7 +477,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma throw new InvalidParameterValueException("can not fine cluster for clusterId " + clusterId); } else { if (cluster.getGuid() == null) { - List hosts = _hostDao.listByCluster(clusterId); + List hosts = listAllHostsInCluster(clusterId); if (!hosts.isEmpty()) { throw new CloudRuntimeException("Guid is not updated for cluster " + clusterId + " need to wait hosts in this cluster up"); } @@ -431,23 +485,18 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } } - String allocationState = cmd.getAllocationState(); - if (allocationState == null) { - allocationState = Host.HostAllocationState.Enabled.toString(); - } - - return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), allocationState); + return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams()); } @Override public List discoverHosts(AddSecondaryStorageCmd cmd) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { Long dcId = cmd.getZoneId(); String url = cmd.getUrl(); - return discoverHostsFull(dcId, null, null, null, url, null, null, "SecondaryStorage", null, null, null); + return discoverHostsFull(dcId, null, null, null, url, null, null, "SecondaryStorage", null, null); } private List discoverHostsFull(Long dcId, Long podId, Long clusterId, String clusterName, String url, String username, String password, String hypervisorType, List hostTags, - Map params, String allocationState) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { + Map params) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException { URI uri = null; // Check if the zone exists in the system @@ -573,7 +622,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma if (resource instanceof KvmDummyResourceBase) { Map details = entry.getValue(); String guid = details.get("guid"); - List kvmHosts = _hostDao.listBy(Host.Type.Routing, clusterId, podId, dcId); + List kvmHosts = listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId); for (HostVO host : kvmHosts) { if (host.getGuid().equalsIgnoreCase(guid)) { if(hostTags != null){ @@ -588,9 +637,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, false); + if (host != null) { + hosts.add(host); } discoverer.postDiscovery(hosts, _nodeId); @@ -613,8 +663,8 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma return _hostDao.findById(hostId); } - @Override - public boolean deleteHost(long hostId, boolean isForced, boolean forceDestroy) { + @DB + private boolean doDeleteHost(long hostId, boolean isForced, boolean isForceDeleteStorage) { User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); // Verify that host exists HostVO host = _hostDao.findById(hostId); @@ -623,16 +673,94 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), host.getDataCenterId()); - processResourceEvent(ResourceListener.EVENT_DELETE_HOST_BEFORE, host); - boolean res = false; - if (Host.Type.SecondaryStorage.equals(host.getType())) { - _secondaryStorageMgr.deleteHost(hostId); - res = true; - } else { - res = _agentMgr.deleteHost(hostId, isForced, forceDestroy, caller); + /* + * TODO: check current agent status and updateAgentStatus to removed. If it was already removed, that means + * someone is deleting host concurrently, return. And consider the situation of CloudStack shutdown during delete. + * A global lock? + * + */ + AgentAttache attache = _agentMgr.findAttache(hostId); + // Get storage pool host mappings here because they can be removed as a part of handleDisconnect later + //TODO: find out the bad boy, what's a buggy logic! + List pools = _storagePoolHostDao.listByHostIdIncludingRemoved(hostId); + + ResourceStateAdapter.DeleteHostAnswer answer = (ResourceStateAdapter.DeleteHostAnswer) dispatchToStateAdapters(ResourceStateAdapter.Event.DELETE_HOST, false, host, new Boolean(isForced), new Boolean(isForceDeleteStorage)); + if (answer.getIsException()) { + return false; } - processResourceEvent(ResourceListener.EVENT_DELETE_HOST_AFTER, host); - return res; + + if (!answer.getIsContinue()) { + return true; + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + _dcDao.releasePrivateIpAddress(host.getPrivateIpAddress(), host.getDataCenterId(), null); + _agentMgr.disconnectWithoutInvestigation(hostId, Status.Event.Remove); + + // delete host details + _hostDetailsDao.deleteDetails(hostId); + + host.setGuid(null); + Long clusterId = host.getClusterId(); + host.setClusterId(null); + _hostDao.update(host.getId(), host); + + _hostDao.remove(hostId); + if (clusterId != null) { + List hosts = listAllHostsInCluster(clusterId); + if (hosts.size() == 0) { + ClusterVO cluster = _clusterDao.findById(clusterId); + cluster.setGuid(null); + _clusterDao.update(clusterId, cluster); + } + } + + try { + resourceStateTransitTo(host, ResourceState.Event.DeleteHost, _nodeId); + } catch (NoTransitionException e) { + s_logger.debug("Cannot transmit host " + host.getId() + "to Enabled state", e); + } + + // Delete the associated entries in host ref table + _storagePoolHostDao.deletePrimaryRecordsForHost(hostId); + + // For pool ids you got, delete local storage host entries in pool table where + for (StoragePoolHostVO pool : pools) { + Long poolId = pool.getPoolId(); + StoragePoolVO storagePool = _storagePoolDao.findById(poolId); + if (storagePool.isLocal() && isForceDeleteStorage) { + storagePool.setUuid(null); + storagePool.setClusterId(null); + _storagePoolDao.update(poolId, storagePool); + _storagePoolDao.remove(poolId); + s_logger.debug("Local storage id=" + poolId + " is removed as a part of host removal id=" + hostId); + } + } + + // delete the op_host_capacity entry + Object[] capacityTypes = { Capacity.CAPACITY_TYPE_CPU, Capacity.CAPACITY_TYPE_MEMORY }; + SearchCriteria hostCapacitySC = _capacityDao.createSearchCriteria(); + hostCapacitySC.addAnd("hostOrPoolId", SearchCriteria.Op.EQ, hostId); + hostCapacitySC.addAnd("capacityType", SearchCriteria.Op.IN, capacityTypes); + _capacityDao.remove(hostCapacitySC); + txn.commit(); + return true; + } + + @Override + public boolean deleteHost(long hostId, boolean isForced, boolean isForceDeleteStorage) { + try { + Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.DeleteHost); + if (result != null) { + return result; + } + } catch (AgentUnavailableException e) { + return false; + } + + return doDeleteHost(hostId, isForced, isForceDeleteStorage); } @Override @@ -650,8 +778,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma return true; } - //don't allow to remove the cluster if it has non-removed hosts - List hosts = _hostDao.listByCluster(cmd.getId()); + List hosts = listAllHostsInCluster(cmd.getId()); if (hosts.size() > 0) { if (s_logger.isDebugEnabled()) { s_logger.debug("Cluster: " + cmd.getId() + " still has hosts, can't remove"); @@ -771,7 +898,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma cluster.setManagedState(Managed.ManagedState.PrepareUnmanaged); _clusterDao.update(cluster.getId(), cluster); txn.commit(); - List hosts = _hostDao.listBy(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); + List hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); for( HostVO host : hosts ) { if(host.getType().equals(Host.Type.Routing) && !host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) && !host.getStatus().equals(Status.Up) && !host.getStatus().equals(Status.Alert) ) { @@ -782,7 +909,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma for( HostVO host : hosts ) { if ( host.getStatus().equals(Status.Up )) { - _agentMgr.disconnect(host.getId()); + umanageHost(host.getId()); } } int retry = 10; @@ -793,7 +920,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma Thread.sleep(20 * 1000); } catch (Exception e) { } - hosts = _hostDao.listBy(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); + hosts = listAllUpAndEnabledHosts(Host.Type.Routing, cluster.getId(), cluster.getPodId(), cluster.getDataCenterId()); for( HostVO host : hosts ) { if ( !host.getStatus().equals(Status.Down) && !host.getStatus().equals(Status.Disconnected) && !host.getStatus().equals(Status.Alert)) { @@ -838,7 +965,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_BEFORE, hostId); - boolean success = _agentMgr.cancelMaintenance(hostId); + boolean success = cancelMaintenance(hostId); processResourceEvent(ResourceListener.EVENT_CANCEL_MAINTENANCE_AFTER, hostId); if (!success) { throw new CloudRuntimeException("Internal error cancelling maintenance."); @@ -847,7 +974,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma } @Override - public Host reconnectHost(ReconnectHostCmd cmd) throws AgentUnavailableException { + public Host reconnectHost(ReconnectHostCmd cmd) { Long hostId = cmd.getId(); HostVO host = _hostDao.findById(hostId); @@ -855,13 +982,69 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma throw new InvalidParameterValueException("Host with id " + hostId.toString() + " doesn't exist"); } - boolean result = _agentMgr.reconnect(hostId); - if (result) { - return host; - } - throw new CloudRuntimeException("Failed to reconnect host with id " + hostId.toString() + ", internal error."); + return (_agentMgr.reconnect(hostId) ? host : null); } + + @Override + public boolean resourceStateTransitTo(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); + } + + 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 { + resourceStateTransitTo(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 = listAllUpAndEnabledHosts(Host.Type.Routing, 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; + } + + public 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(); @@ -872,7 +1055,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma throw new InvalidParameterValueException("Unable to find host with ID: " + hostId + ". Please specify a valid host ID."); } - if (_hostDao.countBy(host.getClusterId(), Status.PrepareForMaintenance, Status.ErrorInMaintenance) > 0) { + if (_hostDao.countBy(host.getClusterId(), ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance) > 0) { throw new InvalidParameterValueException("There are other servers in PrepareForMaintenance OR ErrorInMaintenance STATUS in cluster " + host.getClusterId()); } @@ -882,7 +1065,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 { @@ -926,6 +1109,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma _hostDetailsDao.persist(hostId, hostDetails); } + /* String allocationState = cmd.getAllocationState(); if (allocationState != null) { // Verify that the host exists @@ -949,6 +1133,7 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma _hostDao.update(hostId, host); } + */ List hostTags = cmd.getHostTags(); if (hostTags != null) { @@ -998,4 +1183,751 @@ public class ResourceManagerImpl implements ResourceManager, ResourceService, Ma return _name; } + @Override + public void registerResourceStateAdapter(String name, ResourceStateAdapter adapter) { + if (_resourceStateAdapters.get(name) != null) { + throw new CloudRuntimeException(name + " has registered"); + } + + synchronized (_resourceStateAdapters) { + _resourceStateAdapters.put(name, adapter); + } + } + + @Override + public void unregisterResourceStateAdapter(String name) { + synchronized (_resourceStateAdapters) { + _resourceStateAdapters.remove(name); + } + } + + private Object dispatchToStateAdapters(ResourceStateAdapter.Event event, boolean singleTaker, Object... args) { + synchronized (_resourceStateAdapters) { + Iterator it = _resourceStateAdapters.entrySet().iterator(); + Object result = null; + while (it.hasNext()) { + Map.Entry item = (Map.Entry) it.next(); + ResourceStateAdapter adapter = item.getValue(); + + String msg = new String("Dispatching resource state event " + event + " to " + item.getKey()); + s_logger.debug(msg); + + if (event == ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED) { + result = adapter.createHostVOForConnectedAgent((HostVO) args[0], (StartupCommand[]) args[1]); + if (result != null && singleTaker) { + break; + } + } else if (event == ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_DIRECT_CONNECT) { + result = adapter.createHostVOForDirectConnectAgent((HostVO) args[0], (StartupCommand[]) args[1], (ServerResource) args[2], + (Map) args[3], (List) args[4]); + if (result != null && singleTaker) { + break; + } + } else if (event == ResourceStateAdapter.Event.DELETE_HOST) { + try { + result = adapter.deleteHost((HostVO) args[0], (Boolean) args[1], (Boolean) args[2]); + if (result != null) { + break; + } + } catch (UnableDeleteHostException e) { + s_logger.debug("Adapter " + adapter.getName() + " says unable to delete host", e); + result = new ResourceStateAdapter.DeleteHostAnswer(false, true); + } + } else { + throw new CloudRuntimeException("Unknown resource state event:" + event); + } + } + + return result; + } + } + + @Override + public void checkCIDR(HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask) throws IllegalArgumentException { + if (serverPrivateIP == null) { + return; + } + // 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)) { + s_logger.warn("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + pod.getName() + + " and zone: " + dc.getName()); + throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + + pod.getName() + " and zone: " + dc.getName()); + } + + // 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) { + throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is not compatible with the CIDR of pod: " + + pod.getName() + " and zone: " + dc.getName()); + } + + } + + 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 details, List hostTags, + ResourceStateAdapter.Event stateEvent) { + StartupCommand startup = cmds[0]; + HostVO host = findHostByGuid(startup.getGuid()); + boolean isNew = false; + if (host == null) { + host = findHostByGuid(startup.getGuidWithoutResource()); + } + if (host == null) { + host = new HostVO(startup.getGuid()); + isNew = true; + } + + String dataCenter = startup.getDataCenter(); + String pod = startup.getPod(); + String cluster = startup.getCluster(); + + if (pod != null && dataCenter != null && pod.equalsIgnoreCase("default") && dataCenter.equalsIgnoreCase("default")) { + List 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()); + } + if (resource != null) { + /* null when agent is connected agent */ + host.setResource(resource.getClass().getName()); + } + + host = (HostVO) dispatchToStateAdapters(stateEvent, true, host, cmds, resource, details, hostTags); + if (host == null) { + throw new CloudRuntimeException("No resource state adapter response"); + } + + if (isNew) { + host = _hostDao.persist(host); + } else { + _hostDao.update(host.getId(), host); + } + + try { + resourceStateTransitTo(host, ResourceState.Event.InternalCreated, _nodeId); + /* Agent goes to Connecting status */ + _agentMgr.agentStatusTransitTo(host, Status.Event.AgentConnected, _nodeId); + } catch (Exception e) { + s_logger.debug("Cannot transmit host " + host.getId() + " to Creating state", e); + _agentMgr.agentStatusTransitTo(host, Status.Event.Error, _nodeId); + try { + resourceStateTransitTo(host, ResourceState.Event.Error, _nodeId); + } catch (NoTransitionException e1) { + s_logger.debug("Cannot transmit host " + host.getId() + "to Error state", e); + } + } + + return host; + } + + private Host createHostAndAgent(ServerResource resource, Map details, boolean old, List hostTags, + 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 = findHostByGuid(firstCmd.getGuid()); + if (host == null) { + host = findHostByGuid(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.handleDirectConnectAgent(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); + /* Don't change resource state here since HostVO is already in database, which means resource state has had an appropriate value*/ + } + } + } + + return host; + } + + @Override + public Host createHostAndAgent(Long hostId, ServerResource resource, Map details, boolean old, List hostTags, boolean forRebalance) { + _agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Add); + Host host = createHostAndAgent(resource, details, old, hostTags, forRebalance); + _agentMgr.tapLoadingAgents(hostId, TapAgentsAction.Del); + return host; + } + + @Override + public Host addHost(long zoneId, ServerResource resource, Type hostType, Map 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 details = hostDetails; + String guid = details.get("guid"); + List currentHosts = this.listAllUpAndEnabledHostsInOneZoneByType(hostType, zoneId); + for (HostVO currentHost : currentHosts) { + if (currentHost.getGuid().equals(guid)) { + return currentHost; + } + } + + return createHostAndAgent(resource, hostDetails, true, null, false); + } + + @Override + public HostVO createHostVOForConnectedAgent(StartupCommand[] cmds) { + return createHostVO(cmds, null, null, null, ResourceStateAdapter.Event.CREATE_HOST_VO_FOR_CONNECTED); + } + + private void checkIPConflicts(HostPodVO pod, DataCenterVO dc, String serverPrivateIP, String serverPrivateNetmask, String serverPublicIP, String serverPublicNetmask) { + // If the server's private IP is the same as is public IP, this host has + // a host-only private network. Don't check for conflicts with the + // private IP address table. + if (serverPrivateIP != serverPublicIP) { + if (!_privateIPAddressDao.mark(dc.getId(), pod.getId(), serverPrivateIP)) { + // If the server's private IP address is already in the + // database, return false + List existingPrivateIPs = _privateIPAddressDao.listByPodIdDcIdIpAddress(pod.getId(), dc.getId(), serverPrivateIP); + + assert existingPrivateIPs.size() <= 1 : " How can we get more than one ip address with " + serverPrivateIP; + if (existingPrivateIPs.size() > 1) { + throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is already in use in pod: " + pod.getName() + " and zone: " + dc.getName()); + } + if (existingPrivateIPs.size() == 1) { + DataCenterIpAddressVO vo = existingPrivateIPs.get(0); + if (vo.getInstanceId() != null) { + throw new IllegalArgumentException("The private ip address of the server (" + serverPrivateIP + ") is already in use in pod: " + pod.getName() + " and zone: " + dc.getName()); + } + } + } + } + + if (serverPublicIP != null && !_publicIPAddressDao.mark(dc.getId(), new Ip(serverPublicIP))) { + // If the server's public IP address is already in the database, + // return false + List existingPublicIPs = _publicIPAddressDao.listByDcIdIpAddress(dc.getId(), serverPublicIP); + if (existingPublicIPs.size() > 0) { + throw new IllegalArgumentException("The public ip address of the server (" + serverPublicIP + ") is already in use in zone: " + dc.getName()); + } + } + } + + @Override + public HostVO fillRoutingHostVO(HostVO host, StartupRoutingCommand ssCmd, HypervisorType hyType, Map details, List hostTags) { + if (host.getPodId() == null) { + s_logger.error("Host " + ssCmd.getPrivateIpAddress() + " sent incorrect pod, pod id is null"); + throw new IllegalArgumentException("Host " + ssCmd.getPrivateIpAddress() + " sent incorrect pod, pod id is null"); + } + + ClusterVO clusterVO = _clusterDao.findById(host.getClusterId()); + if (clusterVO.getHypervisorType() != hyType) { + throw new IllegalArgumentException("Can't add host whose hypervisor type is: " + hyType + " into cluster: " + clusterVO.getId() + " whose hypervisor type is: " + + clusterVO.getHypervisorType()); + } + + final Map hostDetails = ssCmd.getHostDetails(); + if (hostDetails != null) { + if (details != null) { + details.putAll(hostDetails); + } else { + details = hostDetails; + } + } + + HostPodVO pod = _podDao.findById(host.getPodId()); + DataCenterVO dc = _dcDao.findById(host.getDataCenterId()); + checkIPConflicts(pod, dc, ssCmd.getPrivateIpAddress(), ssCmd.getPublicIpAddress(), ssCmd.getPublicIpAddress(), ssCmd.getPublicNetmask()); + host.setType(com.cloud.host.Host.Type.Routing); + host.setDetails(details); + host.setCaps(ssCmd.getCapabilities()); + host.setCpus(ssCmd.getCpus()); + host.setTotalMemory(ssCmd.getMemory()); + host.setSpeed(ssCmd.getSpeed()); + host.setHypervisorType(hyType); + return host; + } + + @Override + public void deleteRoutingHost(HostVO host, boolean isForced, boolean forceDestroyStorage) throws UnableDeleteHostException { + if (host.getType() != Host.Type.Routing) { + throw new CloudRuntimeException("Non-Routing host gets in deleteRoutingHost, id is " + host.getId()); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Deleting Host: " + host.getId() + " Guid:" + host.getGuid()); + } + + User caller = _accountMgr.getActiveUser(UserContext.current().getCallerUserId()); + if (forceDestroyStorage) { + // put local storage into mainenance mode, will set all the VMs on + // this local storage into stopped state + StoragePool storagePool = _storageMgr.findLocalStorageOnHost(host.getId()); + if (storagePool != null) { + if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) { + try { + storagePool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId()); + if (storagePool == null) { + s_logger.debug("Failed to set primary storage into maintenance mode"); + throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode"); + } + } catch (Exception e) { + s_logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString()); + throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode, due to: " + e.toString()); + } + } + + List vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId()); + for (VMInstanceVO vm : vmsOnLocalStorage) { + try { + if (!_vmMgr.destroy(vm, caller, _accountMgr.getAccount(vm.getAccountId()))) { + String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId(); + s_logger.warn(errorMsg); + throw new UnableDeleteHostException(errorMsg); + } + } catch (Exception e) { + String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId(); + s_logger.debug(errorMsg, e); + throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); + } + } + } + } else { + // Check if there are vms running/starting/stopping on this host + List vms = _vmDao.listByHostId(host.getId()); + if (!vms.isEmpty()) { + if (isForced) { + // Stop HA disabled vms and HA enabled vms in Stopping state + // Restart HA enabled vms + for (VMInstanceVO vm : vms) { + if (!vm.isHaEnabled() || vm.getState() == State.Stopping) { + s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + host.getId()); + try { + if (!_vmMgr.advanceStop(vm, true, caller, _accountMgr.getAccount(vm.getAccountId()))) { + String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId(); + s_logger.warn(errorMsg); + throw new UnableDeleteHostException(errorMsg); + } + } catch (Exception e) { + String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId(); + s_logger.debug(errorMsg, e); + throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); + } + } else if (vm.isHaEnabled() && (vm.getState() == State.Running || vm.getState() == State.Starting)) { + s_logger.debug("Scheduling restart for vm: " + vm + " " + vm.getState() + " on the host id=" + host.getId()); + _haMgr.scheduleRestart(vm, false); + } + } + } else { + throw new UnableDeleteHostException("Unable to delete the host as there are vms in " + vms.get(0).getState() + + " state using this host and isForced=false specified"); + } + } + } + } + + private boolean doCancelMaintenance(long hostId) { + HostVO host; + host = _hostDao.findById(hostId); + if (host == null || host.getRemoved() != null) { + s_logger.warn("Unable to find host " + hostId); + return true; + } + + /*TODO: think twice about returning true or throwing out exception, I really prefer to exception that always exposes bugs */ + if (host.getResourceState() != ResourceState.PrepareForMaintenance && host.getResourceState() != ResourceState.Maintenance && host.getResourceState() != ResourceState.ErrorInMaintenance) { + throw new CloudRuntimeException("Cannot perform cancelMaintenance when resource state is " + host.getResourceState() + ", hostId = " + hostId); + } + + /*TODO: move to listener */ + _haMgr.cancelScheduledMigrations(host); + List vms = _haMgr.findTakenMigrationWork(); + for (VMInstanceVO vm : vms) { + if (vm.getHostId() != null && vm.getHostId() == hostId) { + s_logger.info("Unable to cancel migration because the vm is being migrated: " + vm); + return false; + } + } + + try { + resourceStateTransitTo(host, ResourceState.Event.AdminCancelMaintenance, _nodeId); + _agentMgr.pullAgentOutMaintenance(hostId); + return true; + } catch (NoTransitionException e) { + s_logger.debug("Cannot transmit host " + host.getId() + "to Enabled state", e); + return false; + } + } + + private boolean cancelMaintenance(long hostId) { + try { + Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.AdminCancelMaintenance); + + if (result != null) { + return result; + } + } catch (AgentUnavailableException e) { + return false; + } + + return doCancelMaintenance(hostId); + } + + @Override + public boolean executeUserRequest(long hostId, ResourceState.Event event) throws AgentUnavailableException { + if (event == ResourceState.Event.AdminAskMaintenace) { + return doMaintain(hostId); + } else if (event == ResourceState.Event.AdminCancelMaintenance) { + return doCancelMaintenance(hostId); + } else if (event == ResourceState.Event.DeleteHost) { + /*TODO: Ask alex why we assume the last two parameters are false*/ + return doDeleteHost(hostId, false, false); + } else if (event == ResourceState.Event.Unmanaged) { + return doUmanageHost(hostId); + } else if (event == ResourceState.Event.UpdatePassword) { + return doUpdateHostPassword(hostId); + } else { + throw new CloudRuntimeException("Received an resource event we are not handling now, " + event); + } + } + + private boolean doUmanageHost(long hostId) { + try { + HostVO host = _hostDao.findById(hostId); + if (host == null) { + s_logger.debug("Cannot find host " + hostId + ", assuming it has been deleted, skip umanage"); + return true; + } + + resourceStateTransitTo(host, ResourceState.Event.Unmanaged, _nodeId); + return true; + } catch (NoTransitionException e) { + s_logger.debug("Cannot transmit host " + hostId + "to Enabled state", e); + return false; + } + } + + + @Override + public boolean umanageHost(long hostId) { + try { + Boolean result = _clusterMgr.propagateResourceEvent(hostId, ResourceState.Event.Unmanaged); + + if (result != null) { + return result; + } + } catch (AgentUnavailableException e) { + return false; + } + + return doUmanageHost(hostId); + } + + private boolean doUpdateHostPassword(long hostId) { + AgentAttache attache = _agentMgr.findAttache(hostId); + if (attache == null) { + return false; + } + + DetailVO nv = _detailsDao.findDetail(hostId, ApiConstants.USERNAME); + String username = nv.getValue(); + nv = _detailsDao.findDetail(hostId, ApiConstants.PASSWORD); + String password = nv.getValue(); + UpdateHostPasswordCommand cmd = new UpdateHostPasswordCommand(username, password); + attache.updatePassword(cmd); + return true; + } + + @Override + public boolean updateHostPassword(UpdateHostPasswordCmd cmd) { + if (cmd.getClusterId() == null) { + // update agent attache password + try { + Boolean result = _clusterMgr.propagateResourceEvent(cmd.getHostId(), ResourceState.Event.UpdatePassword); + if (result != null) { + return result; + } + } catch (AgentUnavailableException e) { + } + + return doUpdateHostPassword(cmd.getHostId()); + } else { + // get agents for the cluster + List hosts = this.listAllHostsInCluster(cmd.getClusterId()); + for (HostVO h : hosts) { + try { + /*FIXME: this is a buggy logic, check with alex. Shouldn't return if propagation return non null*/ + Boolean result = _clusterMgr.propagateResourceEvent(h.getId(), ResourceState.Event.UpdatePassword); + if (result != null) { + return result; + } + + doUpdateHostPassword(cmd.getHostId()); + } catch (AgentUnavailableException e) { + } + } + + return true; + } + } + + @Override + public boolean maintenanceFailed(long hostId) { + HostVO host = _hostDao.findById(hostId); + if (host == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Cant not find host " + hostId); + } + return false; + } else { + try { + return resourceStateTransitTo(host, ResourceState.Event.UnableToMigrate, _nodeId); + } catch (NoTransitionException e) { + s_logger.debug("No next resource state for host " + host.getId() + " while current state is " + host.getResourceState() + " with event " + ResourceState.Event.UnableToMigrate, e); + return false; + } + } + } + + @Override + public List findDirectlyConnectedHosts() { + /* The resource column is not null for direct connected resource */ + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getResource(), Op.NNULL); + sc.addAnd(sc.getEntity().getResourceState(), Op.NIN, ResourceState.Disabled); + return sc.list(); + } + + @Override + public List listAllUpAndEnabledHosts(Type type, Long clusterId, Long podId, long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + if (type != null) { + sc.addAnd(sc.getEntity().getType(), Op.EQ, type); + } + if (clusterId != null) { + sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, clusterId); + } + if (podId != null) { + sc.addAnd(sc.getEntity().getPodId(), Op.EQ, podId); + } + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); + sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); + sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, ResourceState.Enabled); + return sc.list(); + } + + @Override + public List listAllHostsInCluster(long clusterId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, clusterId); + return sc.list(); + } + + @Override + public List listHostsInClusterByStatus(long clusterId, Status status) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, clusterId); + sc.addAnd(sc.getEntity().getStatus(), Op.EQ, status); + return sc.list(); + } + + @Override + public List listAllUpAndEnabledHostsInOneZoneByType(Type type, long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, type); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); + sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up); + sc.addAnd(sc.getEntity().getResourceState(), Op.EQ, ResourceState.Enabled); + return sc.list(); + } + + @Override + public List listAllHostsInOneZoneByType(Type type, long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, type); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); + return sc.list(); + } + + @Override + public List listAllHostsInAllZonesByType(Type type) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, type); + return sc.list(); + } + + @Override + public List listAvailHypervisorInZone(Long hostId, Long zoneId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + if (zoneId != null) { + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, zoneId); + } + if (hostId != null) { + sc.addAnd(sc.getEntity().getId(), Op.EQ, hostId); + } + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing); + List hosts = sc.list(); + + List hypers = new ArrayList(5); + for (HostVO host : hosts) { + hypers.add(host.getHypervisorType()); + } + return hypers; + } + + @Override + public HostVO findHostByGuid(String guid) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getGuid(), Op.EQ, guid); + return sc.find(); + } + + @Override + public HostVO findHostByName(String name) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getName(), Op.EQ, name); + return sc.find(); + } + + @Override + public List listHostsByNameLike(String name) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getName(), Op.LIKE, "%" + name + "%"); + return sc.list(); + } } diff --git a/server/src/com/cloud/resource/ResourceStateAdapter.java b/server/src/com/cloud/resource/ResourceStateAdapter.java new file mode 100755 index 00000000000..18e044f9716 --- /dev/null +++ b/server/src/com/cloud/resource/ResourceStateAdapter.java @@ -0,0 +1,47 @@ +package com.cloud.resource; + +import java.util.List; +import java.util.Map; + +import com.cloud.agent.api.StartupAnswer; +import com.cloud.agent.api.StartupCommand; +import com.cloud.exception.ConnectionException; +import com.cloud.host.HostVO; +import com.cloud.utils.component.Adapter; + +public interface ResourceStateAdapter extends Adapter { + static public enum Event { + CREATE_HOST_VO_FOR_CONNECTED, + CREATE_HOST_VO_FOR_DIRECT_CONNECT, + DELETE_HOST, + } + + static public class DeleteHostAnswer { + private boolean isContinue; + private boolean isException; + + public DeleteHostAnswer(boolean isContinue) { + this.isContinue = isContinue; + this.isException = false; + } + + public DeleteHostAnswer(boolean isContinue, boolean isException) { + this.isContinue = isContinue; + this.isException = isException; + } + + public boolean getIsContinue() { + return this.isContinue; + } + + public boolean getIsException() { + return this.isException; + } + } + + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd); + + public HostVO createHostVOForDirectConnectAgent(HostVO host, final StartupCommand[] startup, ServerResource resource, Map details, List hostTags); + + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException; +} diff --git a/server/src/com/cloud/secstorage/PremiumSecondaryStorageManagerImpl.java b/server/src/com/cloud/secstorage/PremiumSecondaryStorageManagerImpl.java old mode 100644 new mode 100755 index 3a3d7d4fde6..4293aed37b7 --- a/server/src/com/cloud/secstorage/PremiumSecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/secstorage/PremiumSecondaryStorageManagerImpl.java @@ -18,6 +18,7 @@ import com.cloud.configuration.Config; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceManager; import com.cloud.storage.secondary.SecondaryStorageManagerImpl; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.utils.DateUtil; @@ -45,6 +46,7 @@ public class PremiumSecondaryStorageManagerImpl extends SecondaryStorageManagerI @Inject SecondaryStorageVmDao _secStorageVmDao; @Inject CommandExecLogDao _cmdExecLogDao; @Inject HostDao _hostDao; + @Inject ResourceManager _resourceMgr; protected SearchBuilder ActiveCommandSearch; protected SearchBuilder HostSearch; @@ -68,7 +70,6 @@ public class PremiumSecondaryStorageManagerImpl extends SecondaryStorageManagerI HostSearch.done(); ActiveCommandSearch.done(); - return true; } @@ -135,7 +136,7 @@ public class PremiumSecondaryStorageManagerImpl extends SecondaryStorageManagerI for(Long vmId : vms) { SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findById(vmId); HostVO host; - host = _hostDao.findByName(secStorageVm.getHostName()); + host = _resourceMgr.findHostByName(secStorageVm.getHostName()); if(host != null && host.getStatus() == Status.Up) return new Pair(host, secStorageVm); } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index ecb6cf52126..c17eecc0708 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -171,6 +171,7 @@ import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.NetworkDao; import com.cloud.projects.Project; import com.cloud.projects.ProjectManager; +import com.cloud.resource.ResourceManager; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; @@ -310,6 +311,7 @@ public class ManagementServerImpl implements ManagementServer { private final HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; private final Adapters _hostAllocators; @Inject ProjectManager _projectMgr; + private final ResourceManager _resourceMgr; private final KeystoreManager _ksMgr; @@ -375,6 +377,7 @@ public class ManagementServerImpl implements ManagementServer { _sshKeyPairDao = locator.getDao(SSHKeyPairDao.class); _itMgr = locator.getManager(VirtualMachineManager.class); _ksMgr = locator.getManager(KeystoreManager.class); + _resourceMgr = locator.getManager(ResourceManager.class); _hypervisorCapabilitiesDao = locator.getDao(HypervisorCapabilitiesDao.class); @@ -1378,7 +1381,7 @@ public class ManagementServerImpl implements ManagementServer { } List hypers = null; if( ! isIso ) { - hypers = _hostDao.getAvailHypervisorInZone(null, null); + hypers = _resourceMgr.listAvailHypervisorInZone(null, null); } Set> templateZonePairSet = new HashSet>(); @@ -3412,7 +3415,7 @@ public class ManagementServerImpl implements ManagementServer { String secondaryStorageURL = _storageMgr.getSecondaryStorageURL(zoneId); StoragePoolVO srcPool = _poolDao.findById(volume.getPoolId()); - List storageServers = _hostDao.listByTypeDataCenter(Host.Type.SecondaryStorage, zoneId); + List storageServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.SecondaryStorage, zoneId); HostVO sserver = storageServers.get(0); List extractURLList = _uploadDao.listByTypeUploadStatus(volumeId, Upload.Type.VOLUME, UploadVO.Status.DOWNLOAD_URL_CREATED); @@ -3867,7 +3870,7 @@ public class ManagementServerImpl implements ManagementServer { } } else { // get all the hosts in this cluster - List hosts = _hostDao.listByCluster(cmd.getClusterId()); + List hosts = _resourceMgr.listAllHostsInCluster(cmd.getClusterId()); Transaction txn = Transaction.currentTxn(); txn.start(); for (HostVO h : hosts) { diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java index 9f429575d18..e7f27be330a 100755 --- a/server/src/com/cloud/server/StatsCollector.java +++ b/server/src/com/cloud/server/StatsCollector.java @@ -46,6 +46,7 @@ import com.cloud.host.HostStats; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceState; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StoragePoolVO; @@ -55,6 +56,7 @@ import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.StoragePoolDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -83,7 +85,8 @@ public class StatsCollector { private final VolumeDao _volsDao; private final StoragePoolDao _storagePoolDao; private final StorageManager _storageManager; - private final StoragePoolHostDao _storagePoolHostDao; + private final StoragePoolHostDao _storagePoolHostDao; + private final SecondaryStorageVmManager _ssvmMgr; private ConcurrentHashMap _hostStats = new ConcurrentHashMap(); private final ConcurrentHashMap _VmStats = new ConcurrentHashMap(); @@ -111,7 +114,8 @@ public class StatsCollector { private StatsCollector(Map configs) { ComponentLocator locator = ComponentLocator.getLocator(ManagementServer.Name); _agentMgr = locator.getManager(AgentManager.class); - _userVmMgr = locator.getManager(UserVmManager.class); + _userVmMgr = locator.getManager(UserVmManager.class); + _ssvmMgr = locator.getManager(SecondaryStorageVmManager.class); _hostDao = locator.getDao(HostDao.class); _userVmDao = locator.getDao(UserVmDao.class); _volsDao = locator.getDao(VolumeDao.class); @@ -153,7 +157,8 @@ public class StatsCollector { s_logger.debug("HostStatsCollector is running..."); SearchCriteria sc = _hostDao.createSearchCriteria(); - sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); + sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); + sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance); sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.Storage.toString()); sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.ConsoleProxy.toString()); sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.SecondaryStorage.toString()); @@ -193,6 +198,7 @@ public class StatsCollector { SearchCriteria sc = _hostDao.createSearchCriteria(); sc.addAnd("status", SearchCriteria.Op.EQ, Status.Up.toString()); + sc.addAnd("resourceState", SearchCriteria.Op.NIN, ResourceState.Maintenance, ResourceState.PrepareForMaintenance, ResourceState.ErrorInMaintenance); sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.Storage.toString()); sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.ConsoleProxy.toString()); sc.addAnd("type", SearchCriteria.Op.NEQ, Host.Type.SecondaryStorage.toString()); @@ -265,7 +271,7 @@ public class StatsCollector { s_logger.debug("StorageCollector is running..."); } - List hosts = _hostDao.listSecondaryStorageHosts(); + List hosts = _ssvmMgr.listSecondaryStorageHostsInAllZones(); ConcurrentHashMap storageStats = new ConcurrentHashMap(); for (HostVO host : hosts) { if ( host.getStorageUrl() == null ) { diff --git a/server/src/com/cloud/storage/OCFS2ManagerImpl.java b/server/src/com/cloud/storage/OCFS2ManagerImpl.java index 8990e897999..82ad8623d6c 100755 --- a/server/src/com/cloud/storage/OCFS2ManagerImpl.java +++ b/server/src/com/cloud/storage/OCFS2ManagerImpl.java @@ -28,6 +28,9 @@ import com.cloud.storage.dao.StoragePoolDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.utils.Ternary; import com.cloud.utils.component.Inject; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteriaService; import com.cloud.utils.exception.CloudRuntimeException; @Local(value ={OCFS2Manager.class}) @@ -129,7 +132,12 @@ public class OCFS2ManagerImpl implements OCFS2Manager, ResourceListener { throw new CloudRuntimeException("Cannot find cluster for ID " + clusterId); } - List hosts = _hostDao.listByInAllStatus(Host.Type.Routing, clusterId, cluster.getPodId(), cluster.getDataCenterId()); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getClusterId(), Op.EQ, clusterId); + sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cluster.getPodId()); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, cluster.getDataCenterId()); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.Routing); + List hosts = sc.list(); if (hosts.isEmpty()) { s_logger.debug("There is no host in cluster " + clusterId + ", no need to prepare OCFS2 nodes"); return true; diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 9892747e447..45d6c7eeff5 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -117,6 +117,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.NetworkManager; import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.org.Grouping; +import com.cloud.resource.ResourceManager; import com.cloud.server.ManagementServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -289,6 +290,10 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag protected OCFS2Manager _ocfs2Mgr; @Inject protected ResourceLimitService _resourceLimitMgr; + @Inject + protected SecondaryStorageVmManager _ssvmMgr; + @Inject + protected ResourceManager _resourceMgr; @Inject(adapter = StoragePoolAllocator.class) protected Adapters _storagePoolAllocators; @@ -361,7 +366,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag List pools = _storagePoolDao.listAll(); // if no pools or 1 pool which is in maintenance - if (pools == null || pools.size() == 0 || (pools.size() == 1 && pools.get(0).getStatus().equals(Status.Maintenance))) { + if (pools == null || pools.size() == 0 || (pools.size() == 1 && pools.get(0).getStatus().equals(StoragePoolStatus.Maintenance))) { return false; } else { return true; @@ -965,7 +970,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag public Pair getAbsoluteIsoPath(long templateId, long dataCenterId) { String isoPath = null; - List storageHosts = _hostDao.listAllBy(Host.Type.SecondaryStorage, dataCenterId); + List storageHosts = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.SecondaryStorage, dataCenterId); if (storageHosts != null) { for (HostVO storageHost : storageHosts) { VMTemplateHostVO templateHostVO = _vmTemplateHostDao.findByHostTemplate(storageHost.getId(), templateId); @@ -993,7 +998,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag @Override public HostVO getSecondaryStorageHost(long zoneId, long tmpltId) { - List hosts = _hostDao.listSecondaryStorageHosts(zoneId); + List hosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); if( hosts == null || hosts.size() == 0) { return null; } @@ -1008,7 +1013,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag @Override public VMTemplateHostVO getTemplateHostRef(long zoneId, long tmpltId, boolean readyOnly) { - List hosts = _hostDao.listSecondaryStorageHosts(zoneId); + List hosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); if( hosts == null || hosts.size() == 0) { return null; } @@ -1034,9 +1039,9 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag @Override public HostVO getSecondaryStorageHost(long zoneId) { - List hosts = _hostDao.listSecondaryStorageHosts(zoneId); + List hosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); if( hosts == null || hosts.size() == 0) { - hosts = _hostDao.listLocalSecondaryStorageHosts(zoneId); + hosts = _ssvmMgr.listLocalSecondaryStorageHostsInOneZone(zoneId); if (hosts.isEmpty()) { return null; } @@ -1050,9 +1055,9 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag @Override public List getSecondaryStorageHosts(long zoneId) { - List hosts = _hostDao.listSecondaryStorageHosts(zoneId); + List hosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); if( hosts == null || hosts.size() == 0) { - hosts = _hostDao.listLocalSecondaryStorageHosts(zoneId); + hosts = _ssvmMgr.listLocalSecondaryStorageHostsInOneZone(zoneId); if (hosts.isEmpty()) { return new ArrayList(); } @@ -1132,7 +1137,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } // Check if there is host up in this cluster - List allHosts = _hostDao.listBy(Host.Type.Routing, clusterId, podId, zoneId); + List allHosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, zoneId); if (allHosts.isEmpty()) { throw new ResourceUnavailableException("No host up to associate a storage pool with in cluster " + clusterId, HostPodVO.class, podId); } @@ -1686,9 +1691,9 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } // Check that there is at least one host in the specified zone - List hosts = _hostDao.listByDataCenter(zoneId); + List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.Routing, zoneId); if (hosts.isEmpty()) { - throw new InvalidParameterValueException("Please add a host in the specified zone before creating a new volume."); + throw new InvalidParameterValueException("There is no workable host in data center id " + zoneId + ", please check hosts' agent status and see if they are disabled"); } if (!sharedPoolExists) { @@ -1934,7 +1939,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } // Cleanup secondary storage hosts - List secondaryStorageHosts = _hostDao.listSecondaryStorageHosts(); + List secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInAllZones(); for (HostVO secondaryStorageHost : secondaryStorageHosts) { try { long hostId = secondaryStorageHost.getId(); @@ -2031,7 +2036,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag } - List hosts = _hostDao.listByClusterStatus(primaryStorage.getClusterId(), Status.Up); + List hosts = _resourceMgr.listHostsInClusterByStatus(primaryStorage.getClusterId(), Status.Up); if( hosts == null || hosts.size() == 0 ) { primaryStorage.setStatus(StoragePoolStatus.Maintenance); _storagePoolDao.update(primaryStorageId, primaryStorage); @@ -2260,7 +2265,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag primaryStorage.setStatus(StoragePoolStatus.Up); _storagePoolDao.update(primaryStorageId, primaryStorage); txn.commit(); - List hosts = _hostDao.listByClusterStatus(primaryStorage.getClusterId(), Status.Up); + List hosts = _resourceMgr.listHostsInClusterByStatus(primaryStorage.getClusterId(), Status.Up); if( hosts == null || hosts.size() == 0 ) { return _storagePoolDao.findById(primaryStorageId); } @@ -3131,7 +3136,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag long dcId = pool.getDataCenterId(); Long podId = pool.getPodId(); - List secHosts = _hostDao.listSecondaryStorageHosts(dcId); + List secHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); //FIXME, for cloudzone, the local secondary storoge if (pool.isLocal() && pool.getPoolType() == StoragePoolType.Filesystem && secHosts.isEmpty()) { diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 4b411c840c7..080e1bc2bd0 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -54,6 +54,7 @@ import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc; @@ -104,6 +105,8 @@ public class DownloadMonitorImpl implements DownloadMonitor { SecondaryStorageVmDao _secStorageVmDao; @Inject AlertManager _alertMgr; + @Inject + SecondaryStorageVmManager _ssvmMgr; @Inject private final DataCenterDao _dcDao = null; @@ -125,6 +128,8 @@ public class DownloadMonitorImpl implements DownloadMonitor { private ClusterDao _clusterDao; @Inject private HostDao _hostDao; + @Inject + private ResourceManager _resourceMgr; private String _name; private Boolean _sslCopy = new Boolean(false); @@ -361,7 +366,7 @@ public class DownloadMonitorImpl implements DownloadMonitor { long templateId = template.getId(); boolean isPublic = template.isFeatured() || template.isPublicTemplate(); for ( DataCenterVO dc : dcs ) { - List ssHosts = _hostDao.listAllSecondaryStorageHosts(dc.getId()); + List ssHosts = _ssvmMgr.listAllTypesSecondaryStorageHostsInOneZone(dc.getId()); for ( HostVO ssHost : ssHosts ) { if (isTemplateUpdateable(templateId, ssHost.getId())) { initiateTemplateDownload(templateId, ssHost); @@ -419,14 +424,14 @@ public class DownloadMonitorImpl implements DownloadMonitor { @Override public void handleSysTemplateDownload(HostVO host) { - List hypers = _hostDao.getAvailHypervisorInZone(host.getId(), host.getDataCenterId()); + List hypers = _resourceMgr.listAvailHypervisorInZone(host.getId(), host.getDataCenterId()); HypervisorType hostHyper = host.getHypervisorType(); if (hypers.contains(hostHyper)) { return; } Set toBeDownloaded = new HashSet(); - List ssHosts = _hostDao.listBy(Host.Type.SecondaryStorage, host.getDataCenterId()); + List ssHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.SecondaryStorage, host.getDataCenterId()); if (ssHosts == null || ssHosts.isEmpty()) { return; } @@ -481,7 +486,7 @@ public class DownloadMonitorImpl implements DownloadMonitor { @Override public void handleTemplateSync(long dcId) { - List ssHosts = _hostDao.listSecondaryStorageHosts(dcId); + List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); for ( HostVO ssHost : ssHosts ) { handleTemplateSync(ssHost); } diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageDiscoverer.java b/server/src/com/cloud/storage/secondary/SecondaryStorageDiscoverer.java index 5f25efdf344..24639f80661 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageDiscoverer.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageDiscoverer.java @@ -32,6 +32,7 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import com.cloud.agent.AgentManager; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.host.HostVO; import com.cloud.host.Status.Event; @@ -78,6 +79,8 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov protected VMTemplateDao _vmTemplateDao = null; @Inject protected ConfigurationDao _configDao = null; + @Inject + protected AgentManager _agentMgr = null; protected SecondaryStorageDiscoverer() { } @@ -290,7 +293,7 @@ public class SecondaryStorageDiscoverer extends DiscovererBase implements Discov public void postDiscovery(List hosts, long msId) { if (_useServiceVM) { for (HostVO h: hosts) { - _hostDao.disconnect(h, Event.AgentDisconnected, msId); + _agentMgr.agentStatusTransitTo(h, Event.AgentDisconnected, msId); } } for (HostVO h: hosts) { diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java b/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java index ac0dced4d19..dfd6b46403d 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageListener.java @@ -28,6 +28,7 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupSecondaryStorageCommand; import com.cloud.agent.api.StartupStorageCommand; +import com.cloud.cluster.ManagementServerNode; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.Status.Event; @@ -71,7 +72,6 @@ public class SecondaryStorageListener implements Listener { @Override public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) { - if ((cmd instanceof StartupStorageCommand) ) { StartupStorageCommand scmd = (StartupStorageCommand)cmd; if (scmd.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE ) { @@ -82,7 +82,6 @@ public class SecondaryStorageListener implements Listener { if(s_logger.isInfoEnabled()) { s_logger.info("Received a host startup notification " + cmd); } - _agentMgr.updateStatus(agent, Event.Ready); _ssVmMgr.onAgentConnect(agent.getDataCenterId(), cmd); _ssVmMgr.generateSetupCommand(agent.getId()); _ssVmMgr.generateFirewallConfiguration(agent.getId()); @@ -90,8 +89,6 @@ public class SecondaryStorageListener implements Listener { return; } return; - - } @Override diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java old mode 100644 new mode 100755 index 3eeafa2812a..2c175496ee1 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -18,6 +18,8 @@ package com.cloud.storage.secondary; import java.util.ArrayList; + +import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; @@ -38,6 +40,8 @@ import com.cloud.agent.api.SecStorageSetupAnswer; import com.cloud.agent.api.SecStorageSetupCommand; import com.cloud.agent.api.SecStorageVMSetupCommand; import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupSecondaryStorageCommand; +import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; @@ -69,6 +73,10 @@ import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.network.Networks.TrafficType; import com.cloud.offerings.NetworkOfferingVO; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.SnapshotVO; @@ -79,6 +87,7 @@ import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateHostDao; +import com.cloud.storage.resource.DummySecondaryStorageResource; import com.cloud.storage.template.TemplateConstants; import com.cloud.user.Account; import com.cloud.user.AccountService; @@ -90,6 +99,9 @@ import com.cloud.utils.component.Adapters; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteriaService; import com.cloud.utils.events.SubscriptionMgr; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; @@ -110,6 +122,7 @@ import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.SecondaryStorageVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.storage.Storage; // // Possible secondary storage vm state transition cases @@ -130,7 +143,7 @@ import com.cloud.vm.dao.VMInstanceDao; // because sooner or later, it will be driven into Running state // @Local(value = { SecondaryStorageVmManager.class }) -public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, VirtualMachineGuru, SystemVmLoadScanHandler { +public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, VirtualMachineGuru, SystemVmLoadScanHandler, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(SecondaryStorageManagerImpl.class); private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 @@ -189,6 +202,10 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V protected CapacityDao _capacityDao; @Inject UserVmDetailsDao _vmDetailsDao; + @Inject + protected ResourceManager _resourceMgr; + @Inject + protected SecondaryStorageVmManager _ssvmMgr; private long _capacityScanInterval = DEFAULT_CAPACITY_SCAN_INTERVAL; @@ -248,7 +265,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V return false; } - List ssHosts = _hostDao.listSecondaryStorageHosts(zoneId); + List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); for( HostVO ssHost : ssHosts ) { String secUrl = ssHost.getStorageUrl(); SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl); @@ -273,7 +290,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V String secUrl = cssHost.getStorageUrl(); SecStorageSetupCommand setupCmd = new SecStorageSetupCommand(secUrl); for ( SecondaryStorageVmVO ssVm : alreadyRunning ) { - HostVO host = _hostDao.findByName(ssVm.getInstanceName()); + HostVO host = _resourceMgr.findHostByName(ssVm.getInstanceName()); Answer answer = _agentMgr.easySend(host.getId(), setupCmd); if (answer != null && answer.getResult()) { if (s_logger.isDebugEnabled()) { @@ -394,7 +411,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V continue; } String instanceName = ssVm.getInstanceName(); - HostVO host = _hostDao.findByName(instanceName); + HostVO host = _resourceMgr.findHostByName(instanceName); if ( host == null ) { continue; } @@ -479,7 +496,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V } protected Map createSecStorageVmInstance(long dataCenterId, SecondaryStorageVm.Role role) { - HostVO secHost = _hostDao.findSecondaryStorageHost(dataCenterId); + HostVO secHost = findSecondaryStorageHost(dataCenterId); if (secHost == null) { String msg = "No secondary storage available in zone " + dataCenterId + ", cannot create secondary storage vm"; s_logger.warn(msg); @@ -665,7 +682,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId); if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) { VMTemplateVO template = _templateDao.findSystemVMTemplate(dataCenterId); - HostVO secHost = _hostDao.findSecondaryStorageHost(dataCenterId); + HostVO secHost = _ssvmMgr.findSecondaryStorageHost(dataCenterId); if (secHost == null) { if (s_logger.isDebugEnabled()) { s_logger.debug("No secondary storage available in zone " + dataCenterId + ", wait until it is ready to launch secondary storage vm"); @@ -731,6 +748,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V public boolean stop() { _loadScanner.stop(); _allocLock.releaseRef(); + _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName()); return true; } @@ -807,6 +825,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V if (s_logger.isInfoEnabled()) { s_logger.info("Secondary storage vm Manager is configured."); } + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } @@ -949,7 +968,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V Map details = _vmDetailsDao.findDetails(vm.getId()); vm.setDetails(details); - HostVO secHost = _hostDao.findSecondaryStorageHost(dest.getDataCenter().getId()); + HostVO secHost = _ssvmMgr.findSecondaryStorageHost(dest.getDataCenter().getId()); assert (secHost != null); StringBuilder buf = profile.getBootArgsBuilder(); @@ -1158,7 +1177,7 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V List ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, dataCenterId, State.Running, State.Migrating, State.Starting, State.Stopped, State.Stopping ); int vmSize = (ssVms == null)? 0 : ssVms.size(); - List ssHosts = _hostDao.listSecondaryStorageHosts(dataCenterId); + List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dataCenterId); int hostSize = (ssHosts == null)? 0 : ssHosts.size(); if ( hostSize > vmSize ) { s_logger.info("No secondary storage vms found in datacenter id=" + dataCenterId + ", starting a new one"); @@ -1182,4 +1201,125 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V public void onScanEnd() { } + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + /* Called when Secondary Storage VM connected */ + StartupCommand firstCmd = cmd[0]; + if (!(firstCmd instanceof StartupSecondaryStorageCommand)) { + return null; + } + + host.setType( com.cloud.host.Host.Type.SecondaryStorageVM); + return host; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map details, + List hostTags) { + /* Called when add secondary storage on UI */ + StartupCommand firstCmd = startup[0]; + if (!(firstCmd instanceof StartupStorageCommand)) { + return null; + } + + com.cloud.host.Host.Type type = null; + StartupStorageCommand ssCmd = ((StartupStorageCommand) firstCmd); + if (ssCmd.getHostType() == Host.Type.SecondaryStorageCmdExecutor) { + type = ssCmd.getHostType(); + } else { + if (ssCmd.getResourceType() == Storage.StorageResourceType.SECONDARY_STORAGE) { + type = Host.Type.SecondaryStorage; + if (resource != null && resource instanceof DummySecondaryStorageResource) { + host.setResource(null); + } + } else if (ssCmd.getResourceType() == Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE) { + type = Host.Type.LocalSecondaryStorage; + } else { + type = Host.Type.Storage; + } + + final Map hostDetails = ssCmd.getHostDetails(); + if (hostDetails != null) { + if (details != null) { + details.putAll(hostDetails); + } else { + details = hostDetails; + } + } + + host.setDetails(details); + host.setParent(ssCmd.getParent()); + host.setTotalSize(ssCmd.getTotalSize()); + host.setHypervisorType(HypervisorType.None); + host.setType(type); + if (ssCmd.getNfsShare() != null) { + host.setStorageUrl(ssCmd.getNfsShare()); + } + } + + return host; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException { + if (host.getType() == Host.Type.SecondaryStorage) { + deleteHost(host.getId()); + return new DeleteHostAnswer(false); + } + return null; + } + + @Override + public HostVO findSecondaryStorageHost(long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorage); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); + List storageHosts = sc.list(); + if (storageHosts == null || storageHosts.size() < 1) { + return null; + } else { + Collections.shuffle(storageHosts); + return storageHosts.get(0); + } + } + + @Override + public List listSecondaryStorageHostsInAllZones() { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorage); + return sc.list(); + } + + @Override + public List listSecondaryStorageHostsInOneZone(long dataCenterId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dataCenterId); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorage); + return sc.list(); + } + + @Override + public List listLocalSecondaryStorageHostsInOneZone(long dataCenterId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dataCenterId); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.LocalSecondaryStorage); + return sc.list(); + } + + @Override + public List listAllTypesSecondaryStorageHostsInOneZone(long dataCenterId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dataCenterId); + sc.addAnd(sc.getEntity().getType(), Op.IN, Host.Type.LocalSecondaryStorage, Host.Type.SecondaryStorage); + return sc.list(); + } + + @Override + public List listUpSecondaryStorageVmHost(long dcId) { + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dcId); + sc.addAnd(sc.getEntity().getStatus(), Op.EQ, com.cloud.host.Status.Up); + sc.addAnd(sc.getEntity().getType(), Op.EQ, Host.Type.SecondaryStorageVM); + return sc.list(); + } } diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java old mode 100644 new mode 100755 index 8a1ca50f7d0..7ec22ac795e --- a/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageVmManager.java @@ -17,6 +17,8 @@ */ package com.cloud.storage.secondary; +import java.util.List; + import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.host.HostVO; @@ -44,5 +46,11 @@ public interface SecondaryStorageVmManager extends Manager { public Pair assignSecStorageVm(long zoneId, Command cmd); boolean generateSetupCommand(Long hostId); - boolean deleteHost(Long hostId); + boolean deleteHost(Long hostId); + public HostVO findSecondaryStorageHost(long dcId); + public List listSecondaryStorageHostsInAllZones(); + public List listSecondaryStorageHostsInOneZone(long dataCenterId); + public List listLocalSecondaryStorageHostsInOneZone(long dataCenterId); + public List listAllTypesSecondaryStorageHostsInOneZone(long dataCenterId); + public List listUpSecondaryStorageVmHost(long dcId); } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index d18db0418af..50adc650b07 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -68,6 +68,7 @@ import com.cloud.host.dao.HostDetailsDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.projects.Project; import com.cloud.projects.ProjectManager; +import com.cloud.resource.ResourceManager; import com.cloud.storage.Snapshot; import com.cloud.storage.Snapshot.Status; import com.cloud.storage.Snapshot.Type; @@ -90,6 +91,7 @@ import com.cloud.storage.dao.StoragePoolDao; import com.cloud.storage.dao.SwiftDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; @@ -171,7 +173,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma private SwiftDao _swiftDao; @Inject private ProjectManager _projectMgr; - + @Inject + private SecondaryStorageVmManager _ssvmMgr; + @Inject + private ResourceManager _resourceMgr; String _name; private int _totalRetries; private int _pauseInterval; @@ -389,7 +394,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma if (_volsDao.getHypervisorType(volume.getId()).equals(HypervisorType.KVM)) { StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId()); ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId()); - List hosts = _hostDao.listByCluster(cluster.getId()); + List hosts = _resourceMgr.listAllHostsInCluster(cluster.getId()); if (hosts != null && !hosts.isEmpty()) { HostVO host = hosts.get(0); if (!hostSupportSnapsthot(host)) { @@ -1026,7 +1031,7 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma continue; } - List ssHosts = _hostDao.listSecondaryStorageHosts(dcId); + List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); for ( HostVO ssHost : ssHosts ) { DeleteSnapshotsDirCommand cmd = new DeleteSnapshotsDirCommand(primaryStoragePoolNameLabel, ssHost.getStorageUrl(), dcId, accountId, volumeId, volume.getPath()); Answer answer = null; diff --git a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java index 5eabeced5e8..b9299cf2bcb 100755 --- a/server/src/com/cloud/storage/upload/UploadMonitorImpl.java +++ b/server/src/com/cloud/storage/upload/UploadMonitorImpl.java @@ -48,6 +48,7 @@ import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.resource.ResourceManager; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Upload; import com.cloud.storage.Upload.Mode; @@ -95,6 +96,8 @@ public class UploadMonitorImpl implements UploadMonitor { private AgentManager _agentMgr; @Inject ConfigurationDao _configDao; + @Inject + ResourceManager _resourceMgr; private String _name; private Boolean _sslCopy = new Boolean(false); @@ -165,7 +168,7 @@ public class UploadMonitorImpl implements UploadMonitor { Type type = (template.getFormat() == ImageFormat.ISO) ? Type.ISO : Type.TEMPLATE ; - List storageServers = _serverDao.listByTypeDataCenter(Host.Type.SecondaryStorage, dataCenterId); + List storageServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.SecondaryStorage, dataCenterId); HostVO sserver = storageServers.get(0); UploadVO uploadTemplateObj = new UploadVO(sserver.getId(), template.getId(), new Date(), @@ -264,7 +267,7 @@ public class UploadMonitorImpl implements UploadMonitor { String errorString = ""; boolean success = false; try{ - List storageServers = _serverDao.listByTypeDataCenter(Host.Type.SecondaryStorage, dataCenterId); + List storageServers = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.SecondaryStorage, dataCenterId); if(storageServers == null ){ errorString = "No Storage Server found at the datacenter - " +dataCenterId; throw new CloudRuntimeException(errorString); diff --git a/server/src/com/cloud/template/HyervisorTemplateAdapter.java b/server/src/com/cloud/template/HyervisorTemplateAdapter.java index da7de2005ea..4f09f412b93 100755 --- a/server/src/com/cloud/template/HyervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HyervisorTemplateAdapter.java @@ -29,6 +29,7 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.download.DownloadMonitor; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.user.Account; import com.cloud.utils.component.Inject; import com.cloud.utils.db.DB; @@ -38,6 +39,7 @@ import com.cloud.utils.exception.CloudRuntimeException; public class HyervisorTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter { private final static Logger s_logger = Logger.getLogger(HyervisorTemplateAdapter.class); @Inject DownloadMonitor _downloadMonitor; + @Inject SecondaryStorageVmManager _ssvmMgr; private String validateUrl(String url) { try { @@ -133,10 +135,10 @@ public class HyervisorTemplateAdapter extends TemplateAdapterBase implements Tem if (!template.isCrossZones() && zoneId != null) { DataCenterVO zone = _dcDao.findById(zoneId); zoneName = zone.getName(); - secondaryStorageHosts = _hostDao.listSecondaryStorageHosts(zoneId); + secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId); } else { zoneName = "(all zones)"; - secondaryStorageHosts = _hostDao.listSecondaryStorageHosts(); + secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInAllZones(); } s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); @@ -237,7 +239,7 @@ public class HyervisorTemplateAdapter extends TemplateAdapterBase implements Tem throw new InvalidParameterValueException("The DomR template cannot be deleted."); } - if (zoneId != null && (_hostDao.findSecondaryStorageHost(zoneId) == null)) { + if (zoneId != null && (_ssvmMgr.findSecondaryStorageHost(zoneId) == null)) { throw new InvalidParameterValueException("Failed to find a secondary storage host in the specified zone."); } @@ -248,7 +250,7 @@ public class HyervisorTemplateAdapter extends TemplateAdapterBase implements Tem TemplateProfile profile = super.prepareDelete(cmd); Long zoneId = profile.getZoneId(); - if (zoneId != null && (_hostDao.findSecondaryStorageHost(zoneId) == null)) { + if (zoneId != null && (_ssvmMgr.findSecondaryStorageHost(zoneId) == null)) { throw new InvalidParameterValueException("Failed to find a secondary storage host in the specified zone."); } diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 1560af8b8e9..ca8491f4bb8 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -97,6 +97,7 @@ import com.cloud.storage.dao.VMTemplatePoolDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.download.DownloadMonitor; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.upload.UploadMonitor; import com.cloud.template.TemplateAdapter.TemplateAdapterType; import com.cloud.user.Account; @@ -163,6 +164,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe @Inject HypervisorGuruManager _hvGuruMgr; @Inject AccountService _accountService; @Inject ResourceLimitService _resourceLimitMgr; + @Inject SecondaryStorageVmManager _ssvmMgr; int _primaryStorageDownloadWait; protected SearchBuilder HostTemplateStatesSearch; @@ -517,7 +519,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe @Override @DB public boolean copy(long userId, VMTemplateVO template, HostVO srcSecHost, DataCenterVO srcZone, DataCenterVO dstZone) throws StorageUnavailableException, ResourceAllocationException { - List dstSecHosts = _hostDao.listSecondaryStorageHosts(dstZone.getId()); + List dstSecHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dstZone.getId()); long tmpltId = template.getId(); long dstZoneId = dstZone.getId(); if (dstSecHosts == null || dstSecHosts.isEmpty() ) { @@ -905,7 +907,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe throw new InvalidParameterValueException("Please specify a valid iso."); } - if (zoneId != null && (_hostDao.findSecondaryStorageHost(zoneId) == null)) { + if (zoneId != null && (_ssvmMgr.findSecondaryStorageHost(zoneId) == null)) { throw new InvalidParameterValueException("Failed to find a secondary storage host in the specified zone."); } TemplateAdapter adapter = getAdapter(template.getHypervisorType()); diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index ed4b0c761ae..f4634cd1d57 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -145,6 +145,7 @@ import com.cloud.org.Cluster; import com.cloud.org.Grouping; import com.cloud.projects.Project; import com.cloud.projects.ProjectManager; +import com.cloud.resource.ResourceManager; import com.cloud.server.Criteria; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -349,6 +350,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager protected FirewallManager _firewallMgr; @Inject protected ProjectManager _projectMgr; + @Inject + protected ResourceManager _resourceMgr; protected ScheduledExecutorService _executor = null; protected int _expungeInterval; @@ -3150,7 +3153,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager sc.setParameters("hostIdEQ", hostId); } else { if (hostName != null) { - List hosts = _hostDao.findHostsLike((String) hostName); + List hosts = _resourceMgr.listHostsByNameLike((String) hostName); if (hosts != null & !hosts.isEmpty()) { Long[] hostIds = new Long[hosts.size()]; for (int i = 0; i < hosts.size(); i++) { diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index b86c99103d3..e29b7f5f09a 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -107,6 +107,7 @@ import com.cloud.network.NetworkManager; import com.cloud.network.NetworkVO; import com.cloud.offering.ServiceOffering; import com.cloud.org.Cluster; +import com.cloud.resource.ResourceManager; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; @@ -225,6 +226,9 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene @Inject(adapter = HostAllocator.class) protected Adapters _hostAllocators; + + @Inject + protected ResourceManager _resourceMgr; Map> _vmGurus = new HashMap>(); protected StateMachine2 _stateMachine; @@ -760,9 +764,9 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene StartAnswer startAnswer = cmds.getAnswer(StartAnswer.class); if (startAnswer != null && startAnswer.getResult()) { String host_guid = startAnswer.getHost_guid(); - if (host_guid != null) { - HostVO finalHost = _hostDao.findByGuid(host_guid); - if (finalHost == null) { + if( host_guid != null ) { + HostVO finalHost = _resourceMgr.findHostByGuid(host_guid); + if ( finalHost == null ) { throw new CloudRuntimeException("Host Guid " + host_guid + " doesn't exist in DB, something wrong here"); } destHostId = finalHost.getId(); diff --git a/server/test/com/cloud/agent/MockAgentManagerImpl.java b/server/test/com/cloud/agent/MockAgentManagerImpl.java old mode 100644 new mode 100755 index dc715e24bb2..94818acdacd --- a/server/test/com/cloud/agent/MockAgentManagerImpl.java +++ b/server/test/com/cloud/agent/MockAgentManagerImpl.java @@ -9,6 +9,7 @@ import javax.naming.ConfigurationException; 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; @@ -16,6 +17,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; @@ -115,12 +117,6 @@ public class MockAgentManagerImpl implements AgentManager { return null; } - @Override - public void disconnect(long hostId, Event event, boolean investigate) { - // TODO Auto-generated method stub - - } - @Override public HostStats getHostStatistics(long hostId) { // TODO Auto-generated method stub @@ -151,42 +147,12 @@ public class MockAgentManagerImpl implements AgentManager { return null; } - @Override - public Host addHost(long zoneId, ServerResource resource, Type hostType, Map hostDetails) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean deleteHost(long hostId, boolean isForced, boolean forceDestroy, User caller) { - // TODO Auto-generated method stub - return false; - } - @Override public Pair findPod(VirtualMachineTemplate template, ServiceOfferingVO offering, DataCenterVO dc, long userId, Set avoids) { // TODO Auto-generated method stub return null; } - @Override - public boolean maintain(long hostId) throws AgentUnavailableException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean maintenanceFailed(long hostId) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean cancelMaintenance(long hostId) { - // TODO Auto-generated method stub - return false; - } - @Override public boolean executeUserRequest(long hostId, Event event) throws AgentUnavailableException { // TODO Auto-generated method stub @@ -194,7 +160,7 @@ public class MockAgentManagerImpl implements AgentManager { } @Override - public boolean reconnect(long hostId) throws AgentUnavailableException { + public boolean reconnect(long hostId) { // TODO Auto-generated method stub return false; } @@ -217,19 +183,6 @@ public class MockAgentManagerImpl implements AgentManager { } - @Override - public AgentAttache simulateStart(Long id, ServerResource resource, Map details, boolean old, List hostTags, String allocationState, boolean forRebalance) - throws IllegalArgumentException { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean updateHostPassword(UpdateHostPasswordCmd upasscmd) { - // TODO Auto-generated method stub - return false; - } - @Override public long sendToSecStorage(HostVO ssHost, Command cmd, Listener listener) { // TODO Auto-generated method stub @@ -248,16 +201,52 @@ public class MockAgentManagerImpl implements AgentManager { return null; } - @Override - public void updateStatus(HostVO host, Event event) { - // TODO Auto-generated method stub - + @Override + public boolean tapLoadingAgents(Long hostId, TapAgentsAction action) { + // TODO Auto-generated method stub + return false; } - @Override - public boolean disconnect(long hostId) { - // TODO Auto-generated method stub - return false; + @Override + public AgentAttache handleDirectConnectAgent(HostVO host, StartupCommand[] cmds, ServerResource resource, boolean forRebalance) throws ConnectionException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean agentStatusTransitTo(HostVO host, Event e, long msId) { + // TODO Auto-generated method stub + return false; + } + + @Override + public AgentAttache findAttache(long hostId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean disconnectAgent(HostVO host, Event e, long msId) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void pullAgentToMaintenance(long hostId) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnectWithoutInvestigation(long hostId, Event event) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnectWithInvestigation(long hostId, Event event) { + // TODO Auto-generated method stub + } } diff --git a/server/test/com/cloud/agent/manager/ResourceManagerTest.java b/server/test/com/cloud/agent/manager/ResourceManagerTest.java new file mode 100755 index 00000000000..82f2e24ea86 --- /dev/null +++ b/server/test/com/cloud/agent/manager/ResourceManagerTest.java @@ -0,0 +1,370 @@ +package com.cloud.agent.manager; + +import java.io.Serializable; +import java.lang.reflect.Field; + +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.Before; + +import com.cloud.agent.AgentManager; +import com.cloud.alert.AlertManagerImpl; +import com.cloud.alert.dao.AlertDaoImpl; +import com.cloud.api.BaseCmd; +import com.cloud.api.commands.CreatePodCmd; +import com.cloud.api.commands.CreateZoneCmd; +import com.cloud.ha.HighAvailabilityManagerImpl; +import com.cloud.ha.dao.HighAvailabilityDaoImpl; +import com.cloud.host.dao.HostDaoImpl; +import com.cloud.host.dao.HostTagsDaoImpl; +import com.cloud.storage.OCFS2ManagerImpl; +import com.cloud.storage.StorageManager; +import com.cloud.storage.dao.DiskOfferingDaoImpl; +import com.cloud.storage.dao.GuestOSCategoryDaoImpl; +import com.cloud.storage.dao.GuestOSDaoImpl; +import com.cloud.storage.dao.LaunchPermissionDaoImpl; +import com.cloud.storage.dao.SnapshotDaoImpl; +import com.cloud.storage.dao.SnapshotPolicyDaoImpl; +import com.cloud.storage.dao.SnapshotScheduleDaoImpl; +import com.cloud.storage.dao.StoragePoolHostDaoImpl; +import com.cloud.storage.dao.StoragePoolWorkDaoImpl; +import com.cloud.storage.dao.SwiftDaoImpl; +import com.cloud.storage.dao.UploadDaoImpl; +import com.cloud.storage.dao.VMTemplateDaoImpl; +import com.cloud.storage.dao.VMTemplateHostDaoImpl; +import com.cloud.storage.dao.VMTemplatePoolDaoImpl; +import com.cloud.storage.dao.VMTemplateZoneDaoImpl; +import com.cloud.storage.dao.VolumeDaoImpl; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.Manager; +import com.cloud.utils.component.MockComponentLocator; +import com.cloud.utils.component.ComponentLocator.ComponentInfo; +import com.cloud.utils.db.GenericDao; +import com.cloud.vm.ClusteredVirtualMachineManagerImpl; +import com.cloud.vm.ItWorkDaoImpl; +import com.cloud.vm.UserVmManagerImpl; +import com.cloud.vm.dao.ConsoleProxyDaoImpl; +import com.cloud.vm.dao.DomainRouterDaoImpl; +import com.cloud.vm.dao.InstanceGroupDaoImpl; +import com.cloud.vm.dao.InstanceGroupVMMapDaoImpl; +import com.cloud.vm.dao.NicDaoImpl; +import com.cloud.vm.dao.SecondaryStorageVmDaoImpl; +import com.cloud.vm.dao.UserVmDaoImpl; +import com.cloud.vm.dao.UserVmDetailsDaoImpl; +import com.cloud.vm.dao.VMInstanceDaoImpl; +import com.cloud.storage.dao.StoragePoolDaoImpl; +import com.cloud.storage.download.DownloadMonitorImpl; +import com.cloud.offerings.dao.NetworkOfferingDaoImpl; +import com.cloud.projects.ProjectManagerImpl; +import com.cloud.projects.dao.ProjectAccountDaoImpl; +import com.cloud.projects.dao.ProjectDaoImpl; +import com.cloud.resource.ResourceManagerImpl; +import com.cloud.resourcelimit.ResourceLimitManagerImpl; +import com.cloud.storage.StorageManagerImpl; +import com.cloud.cluster.CheckPointManagerImpl; +import com.cloud.cluster.ClusterFenceManagerImpl; +import com.cloud.cluster.ClusterManagerImpl; +import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl; +import com.cloud.cluster.dao.ManagementServerHostDaoImpl; +import com.cloud.cluster.dao.StackMaidDaoImpl; +import com.cloud.configuration.ConfigurationManagerImpl; +import com.cloud.configuration.ConfigurationService; +import com.cloud.configuration.DefaultInterceptorLibrary; +import com.cloud.configuration.dao.ConfigurationDaoImpl; +import com.cloud.configuration.dao.ResourceCountDaoImpl; +import com.cloud.configuration.dao.ResourceLimitDaoImpl; +import com.cloud.template.TemplateManagerImpl; +import com.cloud.user.AccountManagerImpl; +import com.cloud.user.DomainManagerImpl; +import com.cloud.user.dao.AccountDaoImpl; +import com.cloud.user.dao.SSHKeyPairDaoImpl; +import com.cloud.user.dao.UserAccountDaoImpl; +import com.cloud.user.dao.UserDaoImpl; +import com.cloud.user.dao.UserStatisticsDaoImpl; + +import junit.framework.TestCase; + +import com.cloud.dao.EntityManagerImpl; +import com.cloud.dc.ClusterDetailsDaoImpl; +import com.cloud.dc.dao.AccountVlanMapDaoImpl; +import com.cloud.dc.dao.DataCenterDaoImpl; +import com.cloud.dc.dao.DataCenterIpAddressDaoImpl; +import com.cloud.dc.dao.DcDetailsDaoImpl; +import com.cloud.dc.dao.HostPodDaoImpl; +import com.cloud.dc.dao.ClusterDaoImpl; +import com.cloud.dc.dao.PodVlanMapDaoImpl; +import com.cloud.dc.dao.VlanDaoImpl; +import com.cloud.domain.dao.DomainDaoImpl; +import com.cloud.event.dao.EventDaoImpl; +import com.cloud.event.dao.UsageEventDaoImpl; +import com.cloud.host.dao.HostDetailsDaoImpl; +import com.cloud.hypervisor.HypervisorGuruManagerImpl; +import com.cloud.hypervisor.dao.HypervisorCapabilitiesDaoImpl; +import com.cloud.keystore.KeystoreDaoImpl; +import com.cloud.keystore.KeystoreManagerImpl; +import com.cloud.capacity.CapacityManagerImpl; +import com.cloud.capacity.dao.CapacityDaoImpl; +import com.cloud.certificate.dao.CertificateDaoImpl; +import com.cloud.async.AsyncJobExecutorContextImpl; +import com.cloud.async.AsyncJobManagerImpl; +import com.cloud.async.SyncQueueManagerImpl; +import com.cloud.async.dao.AsyncJobDaoImpl; +import com.cloud.async.dao.SyncQueueDaoImpl; +import com.cloud.async.dao.SyncQueueItemDaoImpl; +import com.cloud.storage.secondary.SecondaryStorageManagerImpl; +import com.cloud.storage.snapshot.SnapshotManagerImpl; +import com.cloud.storage.snapshot.SnapshotSchedulerImpl; +import com.cloud.storage.upload.UploadMonitorImpl; +import com.cloud.consoleproxy.ConsoleProxyManagerImpl; +import com.cloud.secstorage.PremiumSecondaryStorageManagerImpl; +import com.cloud.service.dao.ServiceOfferingDaoImpl; +import com.cloud.maint.UpgradeManagerImpl; +import com.cloud.maint.dao.AgentUpgradeDaoImpl; +import com.cloud.network.NetworkManagerImpl; +import com.cloud.network.dao.FirewallRulesCidrsDaoImpl; +import com.cloud.network.dao.FirewallRulesDaoImpl; +import com.cloud.network.dao.IPAddressDaoImpl; +import com.cloud.network.dao.InlineLoadBalancerNicMapDaoImpl; +import com.cloud.network.dao.LoadBalancerDaoImpl; +import com.cloud.network.dao.LoadBalancerVMMapDaoImpl; +import com.cloud.network.dao.NetworkDaoImpl; +import com.cloud.network.dao.NetworkDomainDaoImpl; +import com.cloud.network.dao.NetworkRuleConfigDaoImpl; +import com.cloud.network.dao.RemoteAccessVpnDaoImpl; +import com.cloud.network.dao.VpnUserDaoImpl; +import com.cloud.network.firewall.FirewallManagerImpl; +import com.cloud.network.lb.ElasticLoadBalancerManagerImpl; +import com.cloud.network.lb.LoadBalancingRulesManagerImpl; +import com.cloud.network.lb.dao.ElasticLbVmMapDaoImpl; +import com.cloud.network.ovs.OvsNetworkManagerImpl; +import com.cloud.network.ovs.OvsTunnelManagerImpl; +import com.cloud.network.ovs.dao.GreTunnelDaoImpl; +import com.cloud.network.ovs.dao.OvsTunnelAccountDaoImpl; +import com.cloud.network.ovs.dao.OvsTunnelDaoImpl; +import com.cloud.network.ovs.dao.OvsWorkDaoImpl; +import com.cloud.network.ovs.dao.VlanMappingDaoImpl; +import com.cloud.network.ovs.dao.VlanMappingDirtyDaoImpl; +import com.cloud.network.ovs.dao.VmFlowLogDaoImpl; +import com.cloud.network.router.VirtualNetworkApplianceManagerImpl; +import com.cloud.network.rules.RulesManagerImpl; +import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl; +import com.cloud.network.security.SecurityGroupManagerImpl2; +import com.cloud.network.security.dao.IngressRuleDaoImpl; +import com.cloud.network.security.dao.SecurityGroupDaoImpl; +import com.cloud.network.security.dao.SecurityGroupRulesDaoImpl; +import com.cloud.network.security.dao.SecurityGroupVMMapDaoImpl; +import com.cloud.network.security.dao.SecurityGroupWorkDaoImpl; +import com.cloud.network.security.dao.VmRulesetLogDaoImpl; +import com.cloud.network.vpn.RemoteAccessVpnManagerImpl; + +public class ResourceManagerTest extends TestCase { + MockComponentLocator _locator; + private static final Logger s_logger = Logger.getLogger(ResourceManagerTest.class); + ConfigurationService _configService; + + @Override + @Before + public void setUp() throws Exception { + _locator = new MockComponentLocator("management-server"); + _locator.addDao("StackMaidDao", StackMaidDaoImpl.class); + _locator.addDao("VMTemplateZoneDao", VMTemplateZoneDaoImpl.class); + _locator.addDao("DomainRouterDao", DomainRouterDaoImpl.class); + _locator.addDao("HostDao", HostDaoImpl.class); + _locator.addDao("VMInstanceDao", VMInstanceDaoImpl.class); + _locator.addDao("UserVmDao", UserVmDaoImpl.class); + ComponentInfo> info = _locator.addDao("ServiceOfferingDao", ServiceOfferingDaoImpl.class); + info.addParameter("cache.size", "50"); + info.addParameter("cache.time.to.live", "600"); + info = _locator.addDao("DiskOfferingDao", DiskOfferingDaoImpl.class); + info.addParameter("cache.size", "50"); + info.addParameter("cache.time.to.live", "600"); + info = _locator.addDao("DataCenterDao", DataCenterDaoImpl.class); + info.addParameter("cache.size", "50"); + info.addParameter("cache.time.to.live", "600"); + info = _locator.addDao("HostPodDao", HostPodDaoImpl.class); + info.addParameter("cache.size", "50"); + info.addParameter("cache.time.to.live", "600"); + _locator.addDao("IPAddressDao", IPAddressDaoImpl.class); + info = _locator.addDao("VlanDao", VlanDaoImpl.class); + info.addParameter("cache.size", "30"); + info.addParameter("cache.time.to.live", "3600"); + _locator.addDao("PodVlanMapDao", PodVlanMapDaoImpl.class); + _locator.addDao("AccountVlanMapDao", AccountVlanMapDaoImpl.class); + _locator.addDao("VolumeDao", VolumeDaoImpl.class); + _locator.addDao("EventDao", EventDaoImpl.class); + info = _locator.addDao("UserDao", UserDaoImpl.class); + info.addParameter("cache.size", "5000"); + info.addParameter("cache.time.to.live", "300"); + _locator.addDao("UserStatisticsDao", UserStatisticsDaoImpl.class); + _locator.addDao("FirewallRulesDao", FirewallRulesDaoImpl.class); + _locator.addDao("LoadBalancerDao", LoadBalancerDaoImpl.class); + _locator.addDao("NetworkRuleConfigDao", NetworkRuleConfigDaoImpl.class); + _locator.addDao("LoadBalancerVMMapDao", LoadBalancerVMMapDaoImpl.class); + _locator.addDao("DataCenterIpAddressDao", DataCenterIpAddressDaoImpl.class); + _locator.addDao("SecurityGroupDao", SecurityGroupDaoImpl.class); + _locator.addDao("IngressRuleDao", IngressRuleDaoImpl.class); + _locator.addDao("SecurityGroupVMMapDao", SecurityGroupVMMapDaoImpl.class); + _locator.addDao("SecurityGroupRulesDao", SecurityGroupRulesDaoImpl.class); + _locator.addDao("SecurityGroupWorkDao", SecurityGroupWorkDaoImpl.class); + _locator.addDao("VmRulesetLogDao", VmRulesetLogDaoImpl.class); + _locator.addDao("AlertDao", AlertDaoImpl.class); + _locator.addDao("CapacityDao", CapacityDaoImpl.class); + _locator.addDao("DomainDao", DomainDaoImpl.class); + _locator.addDao("AccountDao", AccountDaoImpl.class); + _locator.addDao("ResourceLimitDao", ResourceLimitDaoImpl.class); + _locator.addDao("ResourceCountDao", ResourceCountDaoImpl.class); + _locator.addDao("UserAccountDao", UserAccountDaoImpl.class); + _locator.addDao("VMTemplateHostDao", VMTemplateHostDaoImpl.class); + _locator.addDao("UploadDao", UploadDaoImpl.class); + _locator.addDao("VMTemplatePoolDao", VMTemplatePoolDaoImpl.class); + _locator.addDao("LaunchPermissionDao", LaunchPermissionDaoImpl.class); + _locator.addDao("ConfigurationDao", ConfigurationDaoImpl.class); + info = _locator.addDao("VMTemplateDao", VMTemplateDaoImpl.class); + info.addParameter("cache.size", "100"); + info.addParameter("cache.time.to.live", "600"); + info.addParameter("routing.uniquename", "routing"); + _locator.addDao("HighAvailabilityDao", HighAvailabilityDaoImpl.class); + _locator.addDao("ConsoleProxyDao", ConsoleProxyDaoImpl.class); + _locator.addDao("SecondaryStorageVmDao", SecondaryStorageVmDaoImpl.class); + _locator.addDao("ManagementServerHostDao", ManagementServerHostDaoImpl.class); + _locator.addDao("AgentUpgradeDao", AgentUpgradeDaoImpl.class); + _locator.addDao("SnapshotDao", SnapshotDaoImpl.class); + _locator.addDao("AsyncJobDao", AsyncJobDaoImpl.class); + _locator.addDao("SyncQueueDao", SyncQueueDaoImpl.class); + _locator.addDao("SyncQueueItemDao", SyncQueueItemDaoImpl.class); + _locator.addDao("GuestOSDao", GuestOSDaoImpl.class); + _locator.addDao("GuestOSCategoryDao", GuestOSCategoryDaoImpl.class); + _locator.addDao("StoragePoolDao", StoragePoolDaoImpl.class); + _locator.addDao("StoragePoolHostDao", StoragePoolHostDaoImpl.class); + _locator.addDao("DetailsDao", HostDetailsDaoImpl.class); + _locator.addDao("SnapshotPolicyDao", SnapshotPolicyDaoImpl.class); + _locator.addDao("SnapshotScheduleDao", SnapshotScheduleDaoImpl.class); + _locator.addDao("ClusterDao", ClusterDaoImpl.class); + _locator.addDao("CertificateDao", CertificateDaoImpl.class); + _locator.addDao("NetworkConfigurationDao", NetworkDaoImpl.class); + _locator.addDao("NetworkOfferingDao", NetworkOfferingDaoImpl.class); + _locator.addDao("NicDao", NicDaoImpl.class); + _locator.addDao("InstanceGroupDao", InstanceGroupDaoImpl.class); + _locator.addDao("InstanceGroupVMMapDao", InstanceGroupVMMapDaoImpl.class); + _locator.addDao("RemoteAccessVpnDao", RemoteAccessVpnDaoImpl.class); + _locator.addDao("VpnUserDao", VpnUserDaoImpl.class); + _locator.addDao("ItWorkDao", ItWorkDaoImpl.class); + _locator.addDao("FirewallRulesDao", FirewallRulesDaoImpl.class); + _locator.addDao("PortForwardingRulesDao", PortForwardingRulesDaoImpl.class); + _locator.addDao("FirewallRulesCidrsDao", FirewallRulesCidrsDaoImpl.class); + _locator.addDao("SSHKeyPairDao", SSHKeyPairDaoImpl.class); + _locator.addDao("UsageEventDao", UsageEventDaoImpl.class); + _locator.addDao("ClusterDetailsDao", ClusterDetailsDaoImpl.class); + _locator.addDao("UserVmDetailsDao", UserVmDetailsDaoImpl.class); + _locator.addDao("VlanMappingDao", VlanMappingDaoImpl.class); + _locator.addDao("VlanMappingDirtyDao", VlanMappingDirtyDaoImpl.class); + _locator.addDao("OvsWorkDao", OvsWorkDaoImpl.class); + _locator.addDao("VmFlowLogDao", VmFlowLogDaoImpl.class); + _locator.addDao("GreTunnelDao", GreTunnelDaoImpl.class); + _locator.addDao("OvsTunnelDao", OvsTunnelDaoImpl.class); + _locator.addDao("OvsTunnelAccountDao", OvsTunnelAccountDaoImpl.class); + _locator.addDao("StoragePoolWorkDao", StoragePoolWorkDaoImpl.class); + _locator.addDao("HostTagsDao", HostTagsDaoImpl.class); + _locator.addDao("NetworkDomainDao", NetworkDomainDaoImpl.class); + _locator.addDao("KeystoreDao", KeystoreDaoImpl.class); + _locator.addDao("DcDetailsDao", DcDetailsDaoImpl.class); + _locator.addDao("SwiftDao", SwiftDaoImpl.class); + _locator.addDao("AgentTransferMapDao", HostTransferMapDaoImpl.class); + _locator.addDao("ProjectDao", ProjectDaoImpl.class); + _locator.addDao("InlineLoadBalancerNicMapDao", InlineLoadBalancerNicMapDaoImpl.class); + _locator.addDao("ElasticLbVmMap", ElasticLbVmMapDaoImpl.class); + _locator.addDao("ProjectsAccountDao", ProjectAccountDaoImpl.class); + info = _locator.addDao("HypervisorCapabilitiesDao", HypervisorCapabilitiesDaoImpl.class); + info.addParameter("cache.size", "100"); + info.addParameter("cache.time.to.live", "600"); + + _locator.addManager("StackMaidManager", CheckPointManagerImpl.class); + _locator.addManager("account manager", AccountManagerImpl.class); + _locator.addManager("domain manager", DomainManagerImpl.class); + _locator.addManager("resource limit manager", ResourceLimitManagerImpl.class); + _locator.addManager("configuration manager", ConfigurationManagerImpl.class); + _locator.addManager("network manager", NetworkManagerImpl.class); + _locator.addManager("download manager", DownloadMonitorImpl.class); + _locator.addManager("upload manager", UploadMonitorImpl.class); + _locator.addManager("keystore manager", KeystoreManagerImpl.class); + _locator.addManager("secondary storage vm manager", SecondaryStorageManagerImpl.class); + _locator.addManager("vm manager", UserVmManagerImpl.class); + _locator.addManager("upgrade manager", UpgradeManagerImpl.class); + _locator.addManager("StorageManager", StorageManagerImpl.class); + _locator.addManager("SyncQueueManager", SyncQueueManagerImpl.class); + _locator.addManager("AsyncJobManager", AsyncJobManagerImpl.class); + _locator.addManager("AsyncJobExecutorContext", AsyncJobExecutorContextImpl.class); + _locator.addManager("HA Manager", HighAvailabilityManagerImpl.class); + _locator.addManager("Alert Manager", AlertManagerImpl.class); + _locator.addManager("Template Manager", TemplateManagerImpl.class); + _locator.addManager("Snapshot Manager", SnapshotManagerImpl.class); + _locator.addManager("SnapshotScheduler", SnapshotSchedulerImpl.class); + _locator.addManager("SecurityGroupManager", SecurityGroupManagerImpl2.class); + _locator.addManager("DomainRouterManager", VirtualNetworkApplianceManagerImpl.class); + _locator.addManager("EntityManager", EntityManagerImpl.class); + _locator.addManager("LoadBalancingRulesManager", LoadBalancingRulesManagerImpl.class); + _locator.addManager("RulesManager", RulesManagerImpl.class); + _locator.addManager("RemoteAccessVpnManager", RemoteAccessVpnManagerImpl.class); + _locator.addManager("OvsNetworkManager", OvsNetworkManagerImpl.class); + _locator.addManager("OvsTunnelManager", OvsTunnelManagerImpl.class); + _locator.addManager("Capacity Manager", CapacityManagerImpl.class); + _locator.addManager("Cluster Manager", ClusterManagerImpl.class); + _locator.addManager("VirtualMachineManager", ClusteredVirtualMachineManagerImpl.class); + _locator.addManager("HypervisorGuruManager", HypervisorGuruManagerImpl.class); + _locator.addManager("ClusterFenceManager", ClusterFenceManagerImpl.class); + _locator.addManager("ResourceManager", ResourceManagerImpl.class); + + _locator.addManager("OCFS2Manager", OCFS2ManagerImpl.class); + _locator.addManager("FirewallManager", FirewallManagerImpl.class); + ComponentInfo info1 = _locator.addManager("ConsoleProxyManager", ConsoleProxyManagerImpl.class); + info1.addParameter("consoleproxy.sslEnabled", "true"); + _locator.addManager("ClusteredAgentManager", ClusteredAgentManagerImpl.class); + _locator.addManager("ProjectManager", ProjectManagerImpl.class); + _locator.addManager("ElasticLoadBalancerManager", ElasticLoadBalancerManagerImpl.class); + + _locator.makeActive(null); + _configService = ComponentLocator.inject(ConfigurationManagerImpl.class); + } + + private void evaluateCmd(T cmd, String name, Object value) { + try { + Field f = cmd.getClass().getDeclaredField(name); + f.set(cmd, value); + } catch (Exception e) { + s_logger.debug("Unable to evaluate " + cmd.getClass().getName() + "." + name, e); + TestCase.fail(); + } + } + + private void createZone(String zoneName) { + CreateZoneCmd cZone = new CreateZoneCmd(); + evaluateCmd(cZone, "dns1", "10.223.110.254"); + evaluateCmd(cZone, "internalDns1", "10.223.110.254"); + evaluateCmd(cZone, "zoneName", zoneName); + evaluateCmd(cZone, "networkType", "Basic"); + evaluateCmd(cZone, "securitygroupenabled", false); + s_logger.info("Create zone:" + cZone.getZoneName()); + + _configService.createZone(cZone); + } + + private void createPod(String name) { + CreatePodCmd cPod = new CreatePodCmd(); + evaluateCmd(cPod, "netmask", "255.255.255.0"); + + } + + private void deploy100Hosts() { + createZone("test1"); + } + + public void testDeploy100Hosts() { + deploy100Hosts(); + } + + @Override + @After + public void tearDown() throws Exception { + } + +} diff --git a/server/test/com/cloud/agent/manager/SearchCriteria2Test.java b/server/test/com/cloud/agent/manager/SearchCriteria2Test.java new file mode 100755 index 00000000000..dd709e5be3f --- /dev/null +++ b/server/test/com/cloud/agent/manager/SearchCriteria2Test.java @@ -0,0 +1,83 @@ +package com.cloud.agent.manager; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.junit.After; +import org.junit.Before; + +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.host.dao.HostDaoImpl; +import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.MockComponentLocator; +import com.cloud.utils.db.DbTestUtils; +import com.cloud.utils.db.SearchCriteria2; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteriaService; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.vm.dao.VMInstanceDaoImpl; + +import junit.framework.TestCase; + +public class SearchCriteria2Test extends TestCase { + private static final Logger s_logger = Logger.getLogger(SearchCriteria2Test.class); + + @Override + @Before + public void setUp() throws Exception { + DbTestUtils.executeScript("PreviousDatabaseSchema/clean-db.sql", false, true); + MockComponentLocator locator = new MockComponentLocator("management-server"); + locator.addDao("HostDao", HostDaoImpl.class); + locator.addDao("VmInstance", VMInstanceDaoImpl.class); + s_logger.debug("Finding sample data from 2.1.12"); + DbTestUtils.executeScript("PreviousDatabaseSchema/2.2.12-newagentmanager/2.2.12_new_agent_manager_cloud_db_sample.sql", false, true); + } + + public void testSearch() { + ComponentLocator locator = ComponentLocator.getCurrentLocator(); + + HostDao _hostDao = locator.inject(HostDaoImpl.class); + VMInstanceDao _vmDao = locator.inject(VMInstanceDaoImpl.class); + + + s_logger.debug("Test seraching host:"); + SearchCriteriaService sc = SearchCriteria2.create(HostVO.class); + sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Disconnected); + List ups = sc.list(); + for (HostVO vo : ups) { + s_logger.info("Host id: " + vo.getId() + " is Disconnected"); + } + + SearchCriteriaService sc1 = SearchCriteria2.create(VMInstanceVO.class); + sc1.addAnd(sc1.getEntity().getState(), Op.EQ, VirtualMachine.State.Running); + List vms = sc1.list(); + for (VMInstanceVO vm : vms) { + s_logger.info("Vm name:" + vm.getInstanceName()); + } + + sc1 = SearchCriteria2.create(VMInstanceVO.class); + sc1.addAnd(sc1.getEntity().getInstanceName(), Op.EQ, "s-1-TEST"); + VMInstanceVO vo = sc1.find(); + s_logger.info("SSVM name is " + vo.getInstanceName()); + + SearchCriteriaService sc3 = SearchCriteria2.create(HostVO.class, Long.class); + sc3.selectField(sc3.getEntity().getId()); + sc3.addAnd(sc3.getEntity().getStatus(), Op.EQ, Status.Disconnected); + sc3.addAnd(sc3.getEntity().getType(), Op.EQ, Host.Type.Routing); + List hostIds = sc3.list(); + for (Long id : hostIds) { + s_logger.info("Host Id is " + id); + } + } + + @Override + @After + public void tearDown() throws Exception { + } + +} diff --git a/server/test/com/cloud/cluster/CheckPointManagerTest.java b/server/test/com/cloud/cluster/CheckPointManagerTest.java old mode 100644 new mode 100755 index fd932c5ebed..ac2dd041441 --- a/server/test/com/cloud/cluster/CheckPointManagerTest.java +++ b/server/test/com/cloud/cluster/CheckPointManagerTest.java @@ -379,6 +379,18 @@ public class CheckPointManagerTest extends TestCase { @Override public boolean isAgentRebalanceEnabled() { return false; + } + + @Override + public Boolean propagateResourceEvent(long agentId, com.cloud.resource.ResourceState.Event event) throws AgentUnavailableException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean executeResourceUserRequest(long hostId, com.cloud.resource.ResourceState.Event event) throws AgentUnavailableException { + // TODO Auto-generated method stub + return false; } } diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java old mode 100644 new mode 100755 index fa661458be1..e941bb66626 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -93,12 +93,6 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS return false; } - @Override - public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - // TODO Auto-generated method stub - return false; - } - @Override public int getActiveNicsInNetwork(long networkId) { // TODO Auto-generated method stub @@ -501,4 +495,17 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager, NetworkS return null; } + @Override + public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, + InsufficientCapacityException { + // TODO Auto-generated method stub + return false; + } + + @Override + public Long getPodIdForVlan(long vlanDbId) { + // TODO Auto-generated method stub + return null; + } + } diff --git a/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java b/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java old mode 100644 new mode 100755 index d5f448709a9..66f51de461d --- a/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java +++ b/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java @@ -192,4 +192,10 @@ public class MockVirtualMachineManagerImpl implements VirtualMachineManager { return false; } + @Override + public VMInstanceVO findById(long vmId) { + // TODO Auto-generated method stub + return null; + } + } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index cc0f28bc930..6253ddecb86 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -702,7 +702,8 @@ CREATE TABLE `cloud`.`host` ( `disconnected` datetime COMMENT 'Time this was disconnected', `created` datetime COMMENT 'date the host first signed on', `removed` datetime COMMENT 'date removed if not null', - `allocation_state` varchar(32) NOT NULL DEFAULT 'Enabled' COMMENT 'Is this host enabled for allocation for new resources', + `update_count` bigint unsigned NOT NULL DEFAULT 0 COMMENT 'atomic increase count making status update operation atomical', + `resource_state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'Is this host enabled for allocation for new resources', PRIMARY KEY (`id`), INDEX `i_host__removed`(`removed`), INDEX `i_host__last_ping`(`last_ping`), diff --git a/tools/testClient/resourceMgrTest/__init__.py b/tools/testClient/resourceMgrTest/__init__.py new file mode 100755 index 00000000000..e69de29bb2d diff --git a/tools/testClient/resourceMgrTest/setup.py b/tools/testClient/resourceMgrTest/setup.py new file mode 100755 index 00000000000..a064fc9d929 --- /dev/null +++ b/tools/testClient/resourceMgrTest/setup.py @@ -0,0 +1,73 @@ +''' +Created on Oct 18, 2011 + +@author: frank +''' +from optparse import OptionParser +from configGenerator import * + +if __name__ == '__main__': + parser = OptionParser() + parser.add_option('-o', '--output', action='store', default='./setup.conf', dest='output', help='the path where the json config file generated') + parser.add_option('-m', '--mshost', dest='mshost', help='hostname/ip of management server', action='store') + + (opts, args) = parser.parse_args() + mandatories = ['mshost'] + for m in mandatories: + if not opts.__dict__[m]: + parser.error("mandatory option - " + m +" missing") + + zs = cloudstackConfiguration() + + #Define Zone + z = zone() + z.dns1 = "8.8.8.8" + z.dns2 = "4.4.4.4" + z.internaldns1 = "192.168.110.254" + z.internaldns2 = "192.168.110.253" + z.name = "testZone" + z.networktype = 'Basic' + + #Define SecondaryStorage + ss = secondaryStorage() + ss.url ="nfs://172.16.15.32/export/share/secondary" + z.secondaryStorages.append(ss) + + p = pod() + p.name = "POD-1" + p.gateway = "10.223.64.1" + p.netmask = "255.255.254.0" + p.startip = "10.223.64.50" + p.endip = "10.223.64.60" + + ip = iprange() + ip.vlan="untagged" + ip.gateway = p.gateway + ip.netmask = p.netmask + ip.startip = "10.223.64.70" + ip.endip = "10.223.64.220" + p.guestIpRanges.append(ip) + + c = cluster() + c.clustername = "CLUSTER-1" + c.clustertype = "CloudManaged" + c.hypervisor = "Simulator" + p.clusters.append(c) + + z.pods.append(p) + zs.zones.append(z) + + '''Add one mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = opts.mshost + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = opts.mshost + db.user = "root" + db.passwd = "" + zs.dbSvr = db + + generate_setup_config(zs,opts.output) + \ No newline at end of file diff --git a/tools/testClient/resourceMgrTest/testDeploy100Host.py b/tools/testClient/resourceMgrTest/testDeploy100Host.py new file mode 100755 index 00000000000..6d3b1ccaf0a --- /dev/null +++ b/tools/testClient/resourceMgrTest/testDeploy100Host.py @@ -0,0 +1,94 @@ +''' +Created on Oct 18, 2011 + +@author: frank +''' +from cloudstackTestCase import * +from cloudstackAPI import * +import uuid +import threading +import random +import time + +class Task(threading.Thread): + def __init__(self, func, param=None): + super(Task, self).__init__() + self.func = func + self.param = param + + def run(self): + self.func(self.param) + + def doTask(self): + self.start() + +class TestDeploy100Hosts(cloudstackTestCase): + hosts = [] + def deployHost(self, url): + apiClient = self.testClient.getApiClient() + addHostCmd = addHost.addHostCmd() + addHostCmd.hypervisor = "simulator" + addHostCmd.clusterid = 1 + addHostCmd.zoneid = 1 + addHostCmd.podid = 1 + addHostCmd.url = "http://sim/%s"%url + addHostCmd.username = "placeholder" + addHostCmd.password = "placeholder" + addHostResponce = apiClient.addHost(addHostCmd) + return addHostResponce[0].id + + def randomCancelMaintenance(self): + def run(param): + while(1): + try: + interval = random.randint(1, 2) + time.sleep(interval) + if len(self.hosts) == 0: + continue + + index = random.randint(0, len(self.hosts)-1) + hostId = self.hosts[index] + apiClient = self.testClient.getApiClient() + cMaintainCmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cMaintainCmd.id = hostId + response = apiClient.cancelHostMaintenance(cMaintainCmd) + id = response.id + print "Host %s cancelled maintenance mode" % id + except Exception, e: + print e + + t = Task(run) + t.doTask() + + def randomEnterMaintenance(self): + def run(param): + while(1): + try: + interval = random.randint(1, 2) + time.sleep(interval) + if len(self.hosts) == 0: + continue + index = random.randint(0, len(self.hosts)-1) + hostId = self.hosts[index] + apiClient = self.testClient.getApiClient() + maintainCmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + maintainCmd.id = hostId + response = apiClient.prepareHostForMaintenance(maintainCmd) + id = response.id + print "Host %s entered maintenance mode" % id + except Exception, e: + print e + + t = Task(run) + t.doTask() + + + def test_deploy100Hosts(self): + #for i in range(200): + #self.hosts.append(self.deployHost(i)) + for i in range(200): + self.hosts.append(i) + self.randomEnterMaintenance() + self.randomCancelMaintenance() + while(1): time.sleep(10000) + diff --git a/utils/src/com/cloud/utils/SerialVersionUID.java b/utils/src/com/cloud/utils/SerialVersionUID.java index 5bfbb84b339..58d5489ffaa 100755 --- a/utils/src/com/cloud/utils/SerialVersionUID.java +++ b/utils/src/com/cloud/utils/SerialVersionUID.java @@ -66,4 +66,5 @@ public interface SerialVersionUID { public static final long NoTransitionException = Base | 0x26; public static final long CloudExecutionException = Base | 0x27; public static final long CallFailedException = Base | 0x28; + public static final long UnableDeleteHostException = Base | 0x29; } diff --git a/utils/src/com/cloud/utils/db/DatabaseCallbackFilter.java b/utils/src/com/cloud/utils/db/DatabaseCallbackFilter.java old mode 100644 new mode 100755 index 00668443fc2..94236788c4c --- a/utils/src/com/cloud/utils/db/DatabaseCallbackFilter.java +++ b/utils/src/com/cloud/utils/db/DatabaseCallbackFilter.java @@ -28,11 +28,25 @@ public class DatabaseCallbackFilter implements CallbackFilter { } public static boolean checkAnnotation(Method method) { + /*Check self*/ DB db = method.getAnnotation(DB.class); if (db != null) { return db.txn(); } Class clazz = method.getDeclaringClass(); + + /*Check parent method*/ + try { + Method pMethod = clazz.getMethod(method.getName(), method.getParameterTypes()); + db = pMethod.getAnnotation(DB.class); + if (db != null) { + return db.txn(); + } + } catch (SecurityException e) { + } catch (NoSuchMethodException e) { + } + + /*Check class's annotation and ancestor's annotation*/ do { db = clazz.getAnnotation(DB.class); if (db != null) { diff --git a/utils/src/com/cloud/utils/db/GenericDao.java b/utils/src/com/cloud/utils/db/GenericDao.java index 5d661182a62..db1ce101e58 100755 --- a/utils/src/com/cloud/utils/db/GenericDao.java +++ b/utils/src/com/cloud/utils/db/GenericDao.java @@ -253,5 +253,10 @@ public interface GenericDao { boolean unlockFromLockTable(String id); public K getRandomlyIncreasingNextInSequence(Class clazz, String name); - -} \ No newline at end of file + + SearchCriteria2 createSearchCriteria2(Class resultType); + + SearchCriteria2 createSearchCriteria2(); + + public T findOneBy(final SearchCriteria sc); +} diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index 91dcd97e926..f4cd86d8580 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -851,9 +851,10 @@ public abstract class GenericDaoBase implements Gene assert results.size() <= 1 : "Didn't the limiting worked?"; return results.size() == 0 ? null : results.get(0); } - + + @Override @DB(txn=false) - protected T findOneBy(final SearchCriteria sc) { + public T findOneBy(final SearchCriteria sc) { if (_removed != null) { sc.addAnd(_removed.second().field.getName(), SearchCriteria.Op.NULL); } @@ -1726,5 +1727,22 @@ public abstract class GenericDaoBase implements Gene SearchBuilder builder = createSearchBuilder(); return builder.create(); } - + + @Override @DB(txn=false) + public SearchCriteria2 createSearchCriteria2(Class resultType) { + final T entity = (T)_searchEnhancer.create(); + final Factory factory = (Factory)entity; + SearchCriteria2 sc = new SearchCriteria2(entity, resultType, _allAttributes, this); + factory.setCallback(0, sc); + return sc; + } + + @Override @DB(txn=false) + public SearchCriteria2 createSearchCriteria2() { + final T entity = (T)_searchEnhancer.create(); + final Factory factory = (Factory)entity; + SearchCriteria2 sc = new SearchCriteria2(entity, (Class)entity.getClass(), _allAttributes, this); + factory.setCallback(0, sc); + return sc; + } } diff --git a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java old mode 100644 new mode 100755 index 08018a417a8..0ce2355a174 --- a/utils/src/com/cloud/utils/db/GenericSearchBuilder.java +++ b/utils/src/com/cloud/utils/db/GenericSearchBuilder.java @@ -24,6 +24,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.persistence.Transient; + import net.sf.cglib.proxy.Factory; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; @@ -154,24 +156,26 @@ public class GenericSearchBuilder implements MethodInterceptor { @Override public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { String name = method.getName(); - if (name.startsWith("get")) { - String fieldName = Character.toLowerCase(name.charAt(3)) + name.substring(4); - set(fieldName); - return null; - } else if (name.startsWith("is")) { - String fieldName = Character.toLowerCase(name.charAt(2)) + name.substring(3); - set(fieldName); - return null; - } else { - name = name.toLowerCase(); - for (String fieldName : _attrs.keySet()) { - if (name.endsWith(fieldName.toLowerCase())) { - set(fieldName); - return null; - } - } - assert false : "Perhaps you need to make the method start with get or is?"; - } + if (method.getAnnotation(Transient.class) == null) { + if (name.startsWith("get")) { + String fieldName = Character.toLowerCase(name.charAt(3)) + name.substring(4); + set(fieldName); + return null; + } else if (name.startsWith("is")) { + String fieldName = Character.toLowerCase(name.charAt(2)) + name.substring(3); + set(fieldName); + return null; + } else { + name = name.toLowerCase(); + for (String fieldName : _attrs.keySet()) { + if (name.endsWith(fieldName.toLowerCase())) { + set(fieldName); + return null; + } + } + assert false : "Perhaps you need to make the method start with get or is?"; + } + } return methodProxy.invokeSuper(object, args); } diff --git a/utils/src/com/cloud/utils/db/SearchCriteria.java b/utils/src/com/cloud/utils/db/SearchCriteria.java index 1bd1c7f077f..4035a11bb52 100755 --- a/utils/src/com/cloud/utils/db/SearchCriteria.java +++ b/utils/src/com/cloud/utils/db/SearchCriteria.java @@ -115,7 +115,7 @@ public class SearchCriteria { private final Map _attrs; private final ArrayList _conditions; private ArrayList _additionals = null; - private final HashMap _params = new HashMap(); + private HashMap _params = new HashMap(); private int _counter; private HashMap>> _joins; private final ArrayList selects, SelectType selectType, Class resultType, HashMap params) { + this._attrs = attrs; + this._conditions = conditions; + this._selects = selects; + this._selectType = selectType; + this._resultType = resultType; + this._params = params; + this._builder = null; + this._additionals = new ArrayList(); + this._counter = 0; + this._joins = null; + this._groupBy = null; + this._groupByValues = null; + } + protected SearchCriteria(GenericSearchBuilder sb) { this._builder = null; this._attrs = sb._attrs; diff --git a/utils/src/com/cloud/utils/db/SearchCriteria2.java b/utils/src/com/cloud/utils/db/SearchCriteria2.java new file mode 100755 index 00000000000..2872a987e61 --- /dev/null +++ b/utils/src/com/cloud/utils/db/SearchCriteria2.java @@ -0,0 +1,197 @@ +package com.cloud.utils.db; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.persistence.Transient; + +import net.sf.cglib.proxy.Factory; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import com.cloud.utils.db.GenericSearchBuilder.Condition; +import com.cloud.utils.db.GenericSearchBuilder.Select; +import com.cloud.utils.db.SearchCriteria.Func; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.SearchCriteria.SelectType; + +public class SearchCriteria2 implements SearchCriteriaService, MethodInterceptor{ + GenericDao _dao; + final protected Map _attrs; + protected ArrayList _specifiedAttrs; + protected T _entity; + protected ArrayList _conditions; + protected ArrayList(); + } + + for (Attribute attr : _specifiedAttrs) { + Field field = null; + try { + field = _resultType.getDeclaredField(attr.field.getName()); + field.setAccessible(true); + } catch (SecurityException e) { + } catch (NoSuchFieldException e) { + } + _selects.add(new Select(Func.NATIVE, attr, field, null)); + } + + _specifiedAttrs.clear(); + } + + private void constructCondition(String conditionName, String cond, Attribute attr, Op op) { + assert _entity != null : "SearchBuilder cannot be modified once it has been setup"; + assert op == null || _specifiedAttrs.size() == 1 : "You didn't select the attribute."; + assert op != Op.SC : "Call join"; + + GenericSearchBuilder.Condition condition = new GenericSearchBuilder.Condition(conditionName, cond, attr, op); + _conditions.add(condition); + _specifiedAttrs.clear(); + } + + private void setParameters(String conditionName, Object... params) { + assert _conditions.contains(new Condition(conditionName)) : "Couldn't find " + conditionName; + _params.put(conditionName, params); + } + + @Override + public void addAnd(Object useless, Op op, Object...values) { + String uuid = UUID.randomUUID().toString(); + constructCondition(uuid, " AND ", _specifiedAttrs.get(0), op); + setParameters(uuid, values); + } + + @Override + public List list() { + done(); + SearchCriteria sc1 = createSearchCriteria(); + if (isSelectAll()) { + return (List)_dao.search(sc1, null); + } else { + return (List)_dao.customSearch(sc1, null); + } + } + + private boolean isSelectAll() { + return _selects == null || _selects.size() == 0; + } + + @Override + public T getEntity() { + return (T) _entity; + } + + private SearchCriteria createSearchCriteria() { + return new SearchCriteria(_attrs, _conditions, _selects, _selectType, _resultType, _params); + } + + private void set(String name) { + Attribute attr = _attrs.get(name); + assert (attr != null) : "Searching for a field that's not there: " + name; + _specifiedAttrs.add(attr); + } + + private void done() { + if (_entity != null) { + Factory factory = (Factory)_entity; + factory.setCallback(0, null); + _entity = null; + } + + if (_selects == null || _selects.size() == 0) { + _selectType = SelectType.Entity; + assert _entityBeanType.equals(_resultType) : "Expecting " + _entityBeanType + " because you didn't specify any selects but instead got " + _resultType; + return; + } + + for (Select select : _selects) { + if (select.field == null) { + assert (_selects.size() == 1) : "You didn't specify any fields to put the result in but you're specifying more than one select so where should I put the selects?"; + _selectType = SelectType.Single; + return; + } + if (select.func != null) { + _selectType = SelectType.Result; + return; + } + } + + _selectType = SelectType.Fields; + } + + @Override + public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + String name = method.getName(); + if (method.getAnnotation(Transient.class) == null) { + if (name.startsWith("get")) { + String fieldName = Character.toLowerCase(name.charAt(3)) + name.substring(4); + set(fieldName); + return null; + } else if (name.startsWith("is")) { + String fieldName = Character.toLowerCase(name.charAt(2)) + name.substring(3); + set(fieldName); + return null; + } else { + name = name.toLowerCase(); + for (String fieldName : _attrs.keySet()) { + if (name.endsWith(fieldName.toLowerCase())) { + set(fieldName); + return null; + } + } + assert false : "Perhaps you need to make the method start with get or is?"; + } + } + return methodProxy.invokeSuper(object, args); + } + + @Override + public K find() { + assert isSelectAll() : "find doesn't support select search"; + done(); + SearchCriteria sc1 = createSearchCriteria(); + return (K)_dao.findOneBy(sc1); + } + +} diff --git a/utils/src/com/cloud/utils/db/SearchCriteriaService.java b/utils/src/com/cloud/utils/db/SearchCriteriaService.java new file mode 100755 index 00000000000..f4509e8e3de --- /dev/null +++ b/utils/src/com/cloud/utils/db/SearchCriteriaService.java @@ -0,0 +1,13 @@ +package com.cloud.utils.db; + +import java.util.List; + +import com.cloud.utils.db.SearchCriteria.Op; + +public interface SearchCriteriaService { + public void selectField(Object... useless); + public void addAnd(Object useless, Op op, Object...values); + public List list(); + public T getEntity(); + public K find(); +} diff --git a/utils/test/com/cloud/utils/component/MockComponentLocator.java b/utils/test/com/cloud/utils/component/MockComponentLocator.java index a74b3833bd2..cffdb5516ff 100755 --- a/utils/test/com/cloud/utils/component/MockComponentLocator.java +++ b/utils/test/com/cloud/utils/component/MockComponentLocator.java @@ -84,7 +84,9 @@ public class MockComponentLocator extends ComponentLocator { s_callbacks = new Callback[] { NoOp.INSTANCE, new DatabaseCallback()}; s_callbackFilter = new DatabaseCallbackFilter(); s_interceptors.clear(); - resetInterceptors(interceptors); + if (interceptors != null) { + resetInterceptors(interceptors); + } s_tl.set(this); parse("fake file"); }