use of io.cdap.cdap.common.ssh.DefaultSSHSession in project cdap by caskdata.
the class RemoteExecutionTwillPreparer method launch.
@Override
protected void launch(TwillRuntimeSpecification twillRuntimeSpec, RuntimeSpecification runtimeSpec, JvmOptions jvmOptions, Map<String, String> environments, Map<String, LocalFile> localFiles, TimeoutChecker timeoutChecker) throws Exception {
try (SSHSession session = new DefaultSSHSession(sshConfig)) {
// Validate kerberos setting if any
Map<String, String> clusterProperties = cluster.getProperties();
String principal = clusterProperties.get(ClusterProperties.KERBEROS_PRINCIPAL);
String keytab = clusterProperties.get(ClusterProperties.KERBEROS_KEYTAB);
validateKerberos(principal, keytab, session);
String targetPath = session.executeAndWait("mkdir -p ./" + getProgramRunId().getRun(), "echo `pwd`/" + getProgramRunId().getRun()).trim();
// Upload files
localizeFiles(session, localFiles, targetPath, runtimeSpec);
// Upload secrets (service socks proxy, runtime token)
localizeSecrets(session, targetPath);
// Currently we only support one TwillRunnable
String runnableName = runtimeSpec.getName();
int memory = Resources.computeMaxHeapSize(runtimeSpec.getResourceSpecification().getMemorySize(), twillRuntimeSpec.getReservedMemory(runnableName), twillRuntimeSpec.getMinHeapRatio(runnableName));
// Spark env setup script
session.executeAndWait(String.format("bash %s/%s/%s %s/%s/%s %s/%s", targetPath, Constants.Files.RUNTIME_CONFIG_JAR, SETUP_SPARK_SH, targetPath, Constants.Files.RUNTIME_CONFIG_JAR, SETUP_SPARK_PY, targetPath, SPARK_ENV_SH));
// Generates the launch script
byte[] scriptContent = generateLaunchScript(targetPath, runnableName, memory, jvmOptions, environments, principal, keytab).getBytes(StandardCharsets.UTF_8);
// noinspection OctalInteger
session.copy(new ByteArrayInputStream(scriptContent), targetPath, "launcher.sh", scriptContent.length, 0755, null, null);
timeoutChecker.throwIfTimeout();
LOG.info("Starting runnable {} for runId {} with SSH", runnableName, getProgramRunId());
session.executeAndWait(targetPath + "/launcher.sh");
}
}
use of io.cdap.cdap.common.ssh.DefaultSSHSession in project cdap by caskdata.
the class SSHRemoteExecutionService method createServiceProxyTunnel.
/**
* Creates a remote port forwarding SSH tunnel for remote runtime to access CDAP services.
*/
private SSHSession createServiceProxyTunnel() throws IOException {
SSHSession session = new DefaultSSHSession(sshConfig);
ProgramRunId programRunId = getProgramRunId();
// Creates a new remote port forwarding from the session.
// We don't need to care about closing the forwarding as it will last until the session get closed,
// in which the remote port forwarding will be closed automatically
int remotePort = session.createRemotePortForward(0, serviceSocksProxyPort).getRemotePort();
LOG.debug("Service SOCKS proxy started on port {} for program run {}", remotePort, programRunId);
ServiceSocksProxyInfo info = new ServiceSocksProxyInfo(remotePort);
// Upload the service socks proxy information to the remote runtime
String targetPath = session.executeAndWait("echo `pwd`/" + programRunId.getRun()).trim();
session.executeAndWait("mkdir -p " + targetPath);
byte[] content = GSON.toJson(info).getBytes(StandardCharsets.UTF_8);
String targetFileName = Constants.RuntimeMonitor.SERVICE_PROXY_FILE + "-" + programRunId.getRun() + ".json";
String tmpFileName = targetFileName + "-" + System.currentTimeMillis() + ".tmp";
// noinspection OctalInteger
session.copy(new ByteArrayInputStream(content), "/tmp", tmpFileName, content.length, 0600, null, null);
session.executeAndWait(String.format("mv /tmp/%s /tmp/%s", tmpFileName, targetFileName));
LOG.debug("Service proxy file uploaded to remote runtime for program run {}", programRunId);
return session;
}
use of io.cdap.cdap.common.ssh.DefaultSSHSession in project cdap by caskdata.
the class SSHRemoteProcessController method killProcess.
private void killProcess(int signal) throws IOException, InterruptedException {
// SSH and kill the process
try (SSHSession session = new DefaultSSHSession(sshConfig)) {
SSHProcess process = session.execute(String.format("pkill -%d -f -- -Dcdap.runid=%s", signal, programRunId.getRun()));
// Reading will be blocked until the process finished
ByteStreams.toByteArray(process.getInputStream());
String err = CharStreams.toString(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8));
int exitCode = process.waitFor();
// If the exit code is 1, it means there is no such process, which is fine from the termination perspective
if (exitCode == 0 || exitCode == 1) {
return;
}
throw new IllegalStateException("Failed to kill remote process for program run " + programRunId + " due to error " + err);
}
}
use of io.cdap.cdap.common.ssh.DefaultSSHSession in project cdap by caskdata.
the class SSHRemoteProcessController method isRunning.
@Override
public boolean isRunning() throws Exception {
// Try to SSH into the host and see if the CDAP runtime process is running or not
try (SSHSession session = new DefaultSSHSession(sshConfig)) {
SSHProcess process = session.execute("pgrep -f -- -Dcdap.runid=" + programRunId.getRun());
// Reading will be blocked until the process finished.
// The output is not needed, just read it to avoid filling up the network buffer.
ByteStreams.toByteArray(process.getInputStream());
ByteStreams.toByteArray(process.getErrorStream());
int exitCode = process.waitFor();
if (exitCode != 0) {
LOG.info("Received exit code {} when checking for remote process for program run {}.", exitCode, programRunId);
}
return exitCode == 0;
} catch (IOException e) {
// If there is error performing SSH, check if the cluster still exist and running
LOG.debug("Failed to use SSH to determine if the remote process is running for {}. Check cluster status instead.", programRunId, e);
Cluster cluster = GSON.fromJson(programOpts.getArguments().getOption(ProgramOptionConstants.CLUSTER), Cluster.class);
String userId = programOpts.getArguments().getOption(ProgramOptionConstants.USER_ID);
ClusterStatus clusterStatus = provisioningService.getClusterStatus(programRunId, programOpts, cluster, userId);
// The cluster status has to be RUNNING in order for the remote process still has a chance that is running
return clusterStatus == ClusterStatus.RUNNING;
}
}
Aggregations