Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,4 +326,18 @@ Getting a standard Ignite executor supporting SSH agent install:
Executor executor = new IgniteSshRemoteExecutor(agent)
.setStrictHostKeyChecking(false)
.setPort(...);
```
```

### Adding your own application

If you look at WebMIs, this shows how to use the framework to control the lifecycle of your own application.

You will need to write classes such as:

- WebMIsServerInstance
- WebMIsInstall
- WebMIsTopology
- WebMIsServerState
- WebMIsServer
- WebMIsConfigurationContext
- WebMIs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public void init(PortAllocator portAllocator) {
* @param license {@link License}
* @param localInstallerPath path of the installer on the local machine
* @param rootInstallationPath directory where installs are stored for caching
* @param env optional env values
*/
public abstract void createLocalInstallFromInstaller(Version version, PackageType packageType, License license, Path localInstallerPath, Path rootInstallationPath, TerracottaCommandLineEnvironment env);

Expand All @@ -84,7 +85,7 @@ public void init(PortAllocator portAllocator) {
* @param packageType {@link PackageType}
* @param localInstallerPath path of the installer on the local machine
* @param rootInstallationPath directory where installs are stored for caching
* @return
* @return path
*/
public abstract Path resolveKitInstallationPath(Version version, PackageType packageType, Path localInstallerPath, Path rootInstallationPath);

Expand Down
29 changes: 16 additions & 13 deletions agent-lib/src/main/java/org/terracotta/angela/agent/Agent.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,9 @@
import org.terracotta.angela.common.net.PortAllocator;
import org.terracotta.angela.common.util.AngelaVersions;
import org.terracotta.angela.common.util.IpUtils;
import org.zeroturnaround.process.PidUtil;
import org.zeroturnaround.process.ProcessUtil;
import org.zeroturnaround.process.Processes;
import org.terracotta.angela.common.util.Pids;
import org.terracotta.angela.common.util.ProcessUtil;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
Expand Down Expand Up @@ -123,6 +121,7 @@ public void close() {

/**
* main method used when starting a new ignite agent locally or remotely
* @param args option arguments
*/
public static void main(String[] args) {
final String instanceName = System.getProperty("angela.instanceName");
Expand Down Expand Up @@ -165,9 +164,13 @@ public void run() {
// let 5 sec for a normal shutdown, otherwise, kill me
sleep(5_000);
logger.warn("Forcefully killing agent after 10 seconds");
ProcessUtil.destroyForcefullyAndWait(Processes.newPidProcess(PidUtil.getMyPid()));
} catch (IOException | InterruptedException e) {
e.printStackTrace();
boolean killed = ProcessUtil.destroyGracefullyOrForcefullyAndWait(Pids.current());
if (!killed) {
logger.warn("Failed to kill agent process {}", Pids.current());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Comment thread
aurbroszniowski marked this conversation as resolved.
logger.warn("Interrupted while waiting to kill agent process", e);
}
}
}.start();
Expand Down Expand Up @@ -214,7 +217,7 @@ public static Agent ignite(UUID group, String instanceName, PortAllocator portAl
int igniteComPort = portReservation.next();
String hostname = IpUtils.getHostName();

AgentID agentID = new AgentID(instanceName, hostname, igniteDiscoveryPort, PidUtil.getMyPid());
AgentID agentID = new AgentID(instanceName, hostname, igniteDiscoveryPort, Pids.current());

logger.info("Starting Ignite agent: {} with com port: {}...", agentID, igniteComPort);

Expand All @@ -236,13 +239,13 @@ public static Agent ignite(UUID group, String instanceName, PortAllocator portAl
cfg.setIgniteHome(IGNITE_DIR.resolve(System.getProperty("user.name")).toString());

cfg.setDiscoverySpi(new TcpDiscoverySpi()
.setLocalPort(igniteDiscoveryPort)
.setLocalPortRange(0) // we must not use the range otherwise Ignite might bind to a port not reserved
.setIpFinder(new TcpDiscoveryVmIpFinder(true).setAddresses(peers)));
.setLocalPort(igniteDiscoveryPort)
.setLocalPortRange(0) // we must not use the range otherwise Ignite might bind to a port not reserved
.setIpFinder(new TcpDiscoveryVmIpFinder(true).setAddresses(peers)));

cfg.setCommunicationSpi(new TcpCommunicationSpi()
.setLocalPort(igniteComPort)
.setLocalPortRange(0)); // we must not use the range otherwise Ignite might bind to a port not reserved
.setLocalPort(igniteComPort)
.setLocalPortRange(0)); // we must not use the range otherwise Ignite might bind to a port not reserved

logger.info("Connecting agent: {} to peers: {}", agentID, peers);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.terracotta.angela.agent.kit.TmsInstall;
import org.terracotta.angela.agent.kit.ToolInstall;
import org.terracotta.angela.agent.kit.VoterInstall;
import org.terracotta.angela.agent.kit.WebMIsInstall;
import org.terracotta.angela.common.TerracottaCommandLineEnvironment;
import org.terracotta.angela.common.TerracottaManagementServerInstance;
import org.terracotta.angela.common.TerracottaManagementServerState;
Expand All @@ -39,6 +40,8 @@
import org.terracotta.angela.common.TerracottaVoterInstance;
import org.terracotta.angela.common.TerracottaVoterState;
import org.terracotta.angela.common.ToolExecutionResult;
import org.terracotta.angela.common.WebMIsServerInstance;
import org.terracotta.angela.common.WebMIsServerState;
import org.terracotta.angela.common.distribution.Distribution;
import org.terracotta.angela.common.distribution.DistributionController;
import org.terracotta.angela.common.metrics.HardwareMetric;
Expand Down Expand Up @@ -91,6 +94,7 @@ public class AgentController {
private final Map<InstanceId, VoterInstall> voterInstalls = new HashMap<>();
private final Map<InstanceId, ToolInstall> clusterToolInstalls = new HashMap<>();
private final Map<InstanceId, ToolInstall> configToolInstalls = new HashMap<>();
private final Map<InstanceId, WebMIsInstall> webMIsInstalls = new HashMap<>();
private final Map<InstanceId, ToolInstall> importToolInstalls = new HashMap<>();

private final AgentID localAgentID;
Expand Down Expand Up @@ -328,7 +332,7 @@ public boolean installImportTool(InstanceId instanceId, String hostName, Distrib

public int startTms(InstanceId instanceId, Map<String, String> envOverrides) {
TerracottaManagementServerInstance serverInstance = tmsInstalls.get(instanceId)
.getTerracottaManagementServerInstance();
.getTerracottaManagementServerInstance();
int port = portAllocator.reserve(1).next();
envOverrides = new LinkedHashMap<>(envOverrides);
envOverrides.put("SERVER_PORT", String.valueOf(port));
Expand All @@ -338,7 +342,7 @@ public int startTms(InstanceId instanceId, Map<String, String> envOverrides) {

public void stopTms(InstanceId instanceId) {
TerracottaManagementServerInstance serverInstance = tmsInstalls.get(instanceId)
.getTerracottaManagementServerInstance();
.getTerracottaManagementServerInstance();
serverInstance.stop();
}

Expand All @@ -359,6 +363,19 @@ public TerracottaManagementServerState getTmsState(InstanceId instanceId) {
return serverInstance.getTerracottaManagementServerState();
}

public void startWebMIs(InstanceId instanceId) {
WebMIsServerInstance serverInstance = webMIsInstalls.get(instanceId)
.getWebMIsServerInstance();
serverInstance.start();
}

public void stopWebMIs(InstanceId instanceId) {
WebMIsServerInstance serverInstance = webMIsInstalls.get(instanceId)
.getWebMIsServerInstance();
serverInstance.stop();
}


public void uninstallTsa(InstanceId instanceId, Topology topology, TerracottaServer terracottaServer, String kitInstallationName, String kitInstallationPath) {
TerracottaInstall terracottaInstall = tsaInstalls.get(instanceId);
if (terracottaInstall != null) {
Expand Down Expand Up @@ -500,6 +517,48 @@ public TerracottaServerState getTsaState(InstanceId instanceId, TerracottaServer
return serverInstance.getTerracottaServerState();
}

public WebMIsServerState getWebMIsState(InstanceId instanceId) {
WebMIsInstall webMIsInstall = webMIsInstalls.get(instanceId);
if (webMIsInstall == null) {
return WebMIsServerState.NOT_INSTALLED;
}
WebMIsServerInstance serverInstance = webMIsInstall.getWebMIsServerInstance();
if (serverInstance == null) {
return WebMIsServerState.NOT_INSTALLED;
}
return serverInstance.getWebMIsServerState();
}

public boolean installWebMIs(InstanceId instanceId, String hostname, Distribution distribution, License license, String kitInstallationName, TerracottaCommandLineEnvironment tcEnv) {
WebMIsInstall webMIsInstall = webMIsInstalls.get(instanceId);
if (webMIsInstall != null) {
logger.debug("Kit for " + hostname + " already installed");
webMIsInstall.addWebMIsServer();
return true;
} else {
Optional<Dirs> dirs = Dirs.discover(instanceId, hostname, distribution, license, kitInstallationName, null);
if (!dirs.isPresent()) {
return false;
}
webMIsInstalls.put(instanceId, new WebMIsInstall(distribution, dirs.get().kitDir, dirs.get().workingDir, tcEnv));
return true;
}
}

public void uninstallWebMIs(InstanceId instanceId, String hostname, Distribution distribution, License license, String kitInstallationName, TerracottaCommandLineEnvironment tcEnv) {
WebMIsInstall webMIsInstall = webMIsInstalls.get(instanceId);
if (webMIsInstall != null) {
webMIsInstall.removeServer();
webMIsInstalls.remove(instanceId);
File installLocation = webMIsInstall.getWorkingDir();
logger.debug("[{}] Uninstalling kit(s) from {} for WebMEthods IS", localAgentID, installLocation);
RemoteKitManager kitManager = new RemoteKitManager(instanceId, distribution, kitInstallationName);
kitManager.deleteInstall(installLocation);
} else {
logger.debug("[{}] No installed kit for " + hostname, localAgentID);
}
}

public Map<ServerSymbolicName, Integer> getProxyGroupPortsForServer(InstanceId instanceId, TerracottaServer terracottaServer) {
TerracottaInstall terracottaInstall = tsaInstalls.get(instanceId);
if (terracottaInstall == null) {
Expand Down Expand Up @@ -544,7 +603,7 @@ public TerracottaVoterState getVoterState(InstanceId instanceId, TerracottaVoter

public void startVoter(InstanceId instanceId, TerracottaVoter terracottaVoter, Map<String, String> envOverrides) {
TerracottaVoterInstance terracottaVoterInstance = voterInstalls.get(instanceId)
.getTerracottaVoterInstance(terracottaVoter);
.getTerracottaVoterInstance(terracottaVoter);
terracottaVoterInstance.start(envOverrides);
}

Expand Down Expand Up @@ -580,14 +639,14 @@ public ToolExecutionResult configTool(InstanceId instanceId, Map<String, String>
public ToolExecutionResult serverJcmd(InstanceId instanceId, TerracottaServer terracottaServer, TerracottaCommandLineEnvironment tcEnv, String... arguments) {
TerracottaServerState tsaState = getTsaState(instanceId, terracottaServer);
if (!EnumSet.of(TerracottaServerState.STARTED_AS_ACTIVE, TerracottaServerState.STARTED_AS_PASSIVE)
.contains(tsaState)) {
.contains(tsaState)) {
throw new IllegalStateException("Cannot control jcmd: server " + terracottaServer.getServerSymbolicName() + " has not started");
}
TerracottaInstall terracottaInstall = tsaInstalls.get(instanceId);
return terracottaInstall.getTerracottaServerInstance(terracottaServer).jcmd(tcEnv, arguments);
}

public ToolExecutionResult clientJcmd(int clientPid, TerracottaCommandLineEnvironment tcEnv, String... arguments) {
public ToolExecutionResult clientJcmd(long clientPid, TerracottaCommandLineEnvironment tcEnv, String... arguments) {
return Jcmd.jcmd(clientPid, tcEnv, arguments);
}

Expand Down Expand Up @@ -617,7 +676,7 @@ public void stopHardwareMonitoring() {
}
}

public void stopClient(InstanceId instanceId, int pid) {
public void stopClient(InstanceId instanceId, long pid) {
try {
logger.info("[{}] killing client '{}' with PID {}", localAgentID, instanceId, pid);
if (!localAgentID.isLocal()) {
Expand Down Expand Up @@ -759,9 +818,9 @@ static Optional<Dirs> discover(InstanceId instanceId, String hostName, Distribut
throw new UncheckedIOException(e);
}
return Optional.of(new Dirs(
kitPath,
workingPath.toFile(),
null
kitPath,
workingPath.toFile(),
null
));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
import org.terracotta.angela.common.util.ExternalLoggers;
import org.terracotta.angela.common.util.LogOutputStream;
import org.terracotta.angela.common.util.OS;
import org.terracotta.angela.common.util.Pids;
import org.zeroturnaround.exec.ProcessExecutor;
import org.zeroturnaround.exec.StartedProcess;
import org.zeroturnaround.process.PidUtil;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -128,7 +128,7 @@ protected void processLine(String line) {
.directory(getClientInstallationPath().toFile());
StartedProcess startedProcess = processExecutor.start();

logger.info("Waiting for spawned agent with PID: {} to be ready...", PidUtil.getPid(startedProcess.getProcess()));
logger.info("Waiting for spawned agent with PID: {} to be ready...", Pids.of(startedProcess.getProcess()));
while (startedProcess.getProcess().isAlive() && !started.get()) {
Thread.sleep(200); // no need to do a short wait because ignite startup is really slow
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public final AgentID getLocalAgentID() {
/**
* A combination of all Ignite agent launched for both remoting (remote agent)
* or for running client jobs, plus the orchestrator
* @return collection of agents
*/
public abstract Collection<AgentID> getAllAgents();

Expand All @@ -79,6 +80,7 @@ public final Collection<AgentID> getSpawnedAgents() {
/**
* Only the Ignite nodes started remotely to control process launching, once per hostname.
* These are not the client agents.
* @return collection of remote agens IDs
*/
public final Collection<AgentID> getRemoteAgentIDs() {
return getAllAgents().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package org.terracotta.angela.agent.com;

import org.terracotta.angela.common.util.IpUtils;
import org.zeroturnaround.process.PidUtil;
import org.terracotta.angela.common.util.Pids;

import java.io.Serializable;
import java.net.InetSocketAddress;
Expand All @@ -31,14 +31,14 @@
public class AgentID implements Serializable {
private static final long serialVersionUID = 1L;

private static final AgentID LOCAL = new AgentID("local", IpUtils.getHostName(), 0, PidUtil.getMyPid());
private static final AgentID LOCAL = new AgentID("local", IpUtils.getHostName(), 0, Pids.current());

private final String name;
private final String hostname;
private final int port;
private final int pid;
private final long pid;

public AgentID(String name, String hostname, int port, int pid) {
public AgentID(String name, String hostname, int port, long pid) {
this.name = requireNonNull(name);
this.hostname = requireNonNull(hostname);
this.port = port;
Expand All @@ -51,7 +51,7 @@ public AgentID(String name, String hostname, int port, int pid) {
}
}

public int getPid() {
public long getPid() {
return pid;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public interface Executor extends AutoCloseable {
* Returns the new agentId that has been spawned.
* If an agent already exists for this hostname,
* empty optional instead.
*
* @param hostname hostname where to start an Agent
* @return AgentID Agent ID
*/
Optional<AgentID> startRemoteAgent(String hostname);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.terracotta.angela.common.util.JDK;
import org.terracotta.angela.common.util.JavaLocationResolver;
import org.terracotta.angela.common.util.LogOutputStream;
import org.terracotta.angela.common.util.ThreadDump;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
Expand Down Expand Up @@ -66,6 +67,7 @@
import static java.util.stream.Collectors.joining;
import static org.terracotta.angela.common.AngelaProperties.ROOT_DIR;
import static org.terracotta.angela.common.AngelaProperties.SSH_PORT;
import static org.terracotta.angela.common.AngelaProperties.SSH_REMOTE_AGENT_START_TIMEOUT_SECONDS;
import static org.terracotta.angela.common.AngelaProperties.SSH_STRICT_HOST_CHECKING;
import static org.terracotta.angela.common.AngelaProperties.SSH_USERNAME;
import static org.terracotta.angela.common.AngelaProperties.SSH_USERNAME_KEY_PATH;
Expand Down Expand Up @@ -467,7 +469,18 @@ public AgentID waitForStartedState() throws InterruptedException {
if (!cmd.isOpen()) {
throw new RuntimeException("agent refused to start");
}
started.await();
long timeoutSeconds = SSH_REMOTE_AGENT_START_TIMEOUT_SECONDS.getLongValue();
boolean completed;
if (timeoutSeconds <= 0) {
started.await();
completed = true;
} else {
completed = started.await(timeoutSeconds, TimeUnit.SECONDS);
}
if (!completed) {
ThreadDump.dump(logger, "Timed out waiting for Ignite agent startup on " + serverName);
throw new RuntimeException("Timed out waiting for Ignite agent to start on " + serverName + " after " + timeoutSeconds + "s");
}
return agentID.get();
}
}
Expand Down
Loading
Loading