use of com.oracle.bedrock.table.Table in project oracle-bedrock by coherence-community.
the class AbstractRemoteApplicationLauncher method launch.
@Override
public A launch(Platform platform, MetaClass<A> metaClass, OptionsByType optionsByType) {
// establish the diagnostics output table
Table diagnosticsTable = new Table();
diagnosticsTable.getOptions().add(Table.orderByColumn(0));
if (platform != null) {
diagnosticsTable.addRow("Target Platform", platform.getName());
}
// ----- establish the launch Options for the Application -----
// add the platform options
OptionsByType launchOptions = OptionsByType.of(platform.getOptions()).addAll(optionsByType);
// add the meta-class options
metaClass.onLaunching(platform, launchOptions);
// ---- establish the default Options ----
// define the PlatformSeparators as Unix if they are not already defined
launchOptions.addIfAbsent(PlatformSeparators.forUnix());
// define the default Platform Shell (assume BASH)
launchOptions.addIfAbsent(Shell.is(Shell.Type.BASH));
// define the "local.address" variable so that is can be used for resolving this platform address
launchOptions.add(Variable.with("local.address", LocalPlatform.get().getAddress().getHostAddress()));
// ----- establish an identity for the application -----
// add a unique runtime id for expression support
launchOptions.add(Variable.with("bedrock.runtime.id", UUID.randomUUID()));
// ----- establish default Profiles for this Platform (and Builder) -----
// auto-detect and add externally defined profiles
launchOptions.addAll(Profiles.getProfiles());
for (Profile profile : launchOptions.getInstancesOf(Profile.class)) {
profile.onLaunching(platform, metaClass, launchOptions);
}
// ----- add the diagnostic table to the options so it can be used by the terminal -----
launchOptions.add(diagnosticsTable);
// ----- prior to launching the application, let the implementation enhance the launch options -----
onLaunching(launchOptions);
// ----- give the MetaClass a last chance to manipulate any options -----
metaClass.onLaunch(platform, launchOptions);
// ----- determine the display name for the application -----
DisplayName displayName = getDisplayName(launchOptions);
// determine the Executable
Executable executable = launchOptions.get(Executable.class);
// ----- deploy remote application artifacts -----
// determine the DeploymentArtifacts based on those specified by the Deployment option
ArrayList<DeploymentArtifact> artifactsToDeploy = new ArrayList<>();
Deployment deployment = launchOptions.get(Deployment.class);
if (deployment != null) {
try {
artifactsToDeploy.addAll(deployment.getDeploymentArtifacts(platform, launchOptions));
} catch (Exception e) {
throw new RuntimeException("Failed to determine artifacts to deploy", e);
}
}
// determine the separators for the platform
PlatformSeparators separators = launchOptions.get(PlatformSeparators.class);
// assume the remote directory is the working directory
WorkingDirectory workingDirectory = launchOptions.getOrSetDefault(WorkingDirectory.class, WorkingDirectory.temporaryDirectory());
File remoteDirectoryFile = workingDirectory.resolve(platform, launchOptions);
if (remoteDirectoryFile == null) {
remoteDirectoryFile = WorkingDirectory.temporaryDirectory().resolve(platform, launchOptions);
}
String remoteDirectory = separators.asPlatformFileName(remoteDirectoryFile.toString());
// Set the resolved working directory back into the options
launchOptions.add(WorkingDirectory.at(remoteDirectoryFile));
if (remoteDirectoryFile != null) {
diagnosticsTable.addRow("Working Directory", remoteDirectoryFile.toString());
}
// Obtain the RemoteShell that will be used to launch the process
RemoteTerminalBuilder terminalBuilder = launchOptions.getOrSetDefault(RemoteTerminalBuilder.class, RemoteTerminals.ssh());
RemoteTerminal terminal = terminalBuilder.build(platform);
// create the working directory
terminal.makeDirectories(remoteDirectory, launchOptions);
// deploy any artifacts required
Deployer deployer = launchOptions.getOrSetDefault(Deployer.class, new SftpDeployer());
DeployedArtifacts deployedArtifacts = deployer.deploy(artifactsToDeploy, remoteDirectory, platform, launchOptions.asArray());
// add the remote directory as something to clean up
deployedArtifacts.add(remoteDirectoryFile);
if (!deployedArtifacts.isEmpty()) {
// when we've deployed artifacts we need to add a listener to clean them up
launchOptions.add(Decoration.of(new ApplicationListener<A>() {
@Override
public void onClosing(A application, OptionsByType optionsByType) {
// nothing to do on closing
}
@Override
public void onClosed(A application, OptionsByType optionsByType) {
Level logLevel = optionsByType.get(LaunchLogging.class).isEnabled() ? Level.INFO : Level.OFF;
try (DiagnosticsRecording diagnostics = DiagnosticsRecording.create("Undeploy Diagnostics for " + application.getName() + " on platform " + platform.getName()).using(LOGGER, logLevel)) {
diagnostics.add("Platform", "Resource");
try (DiagnosticsRecording local = DiagnosticsRecording.section("Local Platform")) {
// clean up the locally created temporary artifacts
artifactsToDeploy.stream().filter(DeploymentArtifact::isTemporary).forEach(artifact -> {
try {
// attempt to remove the local file
artifact.getSourceFile().delete();
// include diagnostics
local.add(artifact.getSourceFile().toString());
} catch (Exception e) {
// log exceptions when attempting to remove local sources
LOGGER.log(Level.WARNING, "Failed to remove temporary " + artifact.toString() + " for application " + application.getName(), e);
// include diagnostics
local.add(artifact.getSourceFile() + " (failed to undeploy)");
}
});
}
// undeploy the deployed artifacts
deployer.undeploy(deployedArtifacts, platform, launchOptions.asArray());
}
}
@Override
public void onLaunched(A application) {
// nothing to do after launching
}
}));
}
// Realize the application arguments
Arguments arguments = launchOptions.get(Arguments.class);
List<String> argList = arguments.resolve(platform, launchOptions);
// Set the actual arguments used back into the options
launchOptions.add(Arguments.of(argList));
// TODO: put a try/catch around the terminal.launch here so we can clean up the RemoteExecutor if
// the application failed to launch
// determine the application class that will represent the running application
Class<? extends A> applicationClass = metaClass.getImplementationClass(platform, launchOptions);
diagnosticsTable.addRow("Application", displayName.resolve(launchOptions));
if (argList.size() > 0) {
diagnosticsTable.addRow("Application Arguments ", argList.stream().collect(Collectors.joining(" ")));
}
diagnosticsTable.addRow("Application Launch Time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
// ----- start the process and establish the application -----
// launch the remote process
RemoteApplicationProcess remoteProcess = terminal.launch(this, applicationClass, launchOptions);
// adapt the remote process into something that the application can use
ApplicationProcess process = adapt(remoteProcess);
// create the Application based on the RemoteApplicationProcess
A application;
try {
// attempt to find a constructor(Platform, JavaApplicationProcess, Options)
Constructor<? extends A> constructor = ReflectionHelper.getCompatibleConstructor(applicationClass, platform.getClass(), process.getClass(), OptionsByType.class);
// create the application
application = constructor.newInstance(platform, process, launchOptions);
} catch (Exception e) {
throw new RuntimeException("Failed to instantiate the Application class specified by the MetaClass:" + metaClass, e);
}
// ----- after launching the application, let the implementation interact with the application -----
onLaunched(application, launchOptions);
// ----- notify the MetaClass that the application has been launched -----
metaClass.onLaunched(platform, application, launchOptions);
for (Profile profile : launchOptions.getInstancesOf(Profile.class)) {
profile.onLaunched(platform, application, launchOptions);
}
// notify the ApplicationListener-based Options that the application has been launched
for (ApplicationListener listener : launchOptions.getInstancesOf(ApplicationListener.class)) {
listener.onLaunched(application);
}
return application;
}
use of com.oracle.bedrock.table.Table in project oracle-bedrock by coherence-community.
the class SftpDeployer method deploy.
@Override
public DeployedArtifacts deploy(List<DeploymentArtifact> artifactsToDeploy, String remoteDirectory, Platform platform, Option... deploymentOptions) {
DeployedArtifacts deployedArtifacts = new DeployedArtifacts();
if (artifactsToDeploy == null || artifactsToDeploy.isEmpty()) {
return deployedArtifacts;
}
if (!(platform instanceof RemotePlatform)) {
throw new IllegalArgumentException("The platform parameter must be an instance of RemotePlatform");
}
Table deploymentTable = new Table();
JSchSocketFactory socketFactory = new JSchSocketFactory();
RemotePlatform remotePlatform = (RemotePlatform) platform;
String userName = remotePlatform.getUserName();
Authentication authentication = remotePlatform.getAuthentication();
String hostName = remotePlatform.getAddress().getHostName();
int port = remotePlatform.getPort();
// Create the deployment options
OptionsByType optionsByType = OptionsByType.empty();
// Add the Platform options
optionsByType.addAll(platform.getOptions());
// Override with specified Options
optionsByType.addAll(deploymentOptions);
// initially there's no session
Session session = null;
try {
// Obtain the connected JSch Session
session = sessionFactory.createSession(hostName, port, userName, authentication, socketFactory, optionsByType);
// ----- deploy remote application artifacts (using sftp) -----
// determine the separators for the platform
PlatformSeparators separators = optionsByType.get(PlatformSeparators.class);
if (artifactsToDeploy.size() > 0) {
ChannelSftp sftpChannel = null;
try {
// open an sftp channel that we can use to copy over the artifacts
sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect(session.getTimeout());
try {
// Obtain the status of the remote directory
sftpChannel.lstat(remoteDirectory);
} catch (SftpException _ignored) {
// the remote directory does not exist so attempt to create it
sftpChannel.mkdir(remoteDirectory);
// add the directory as something to clean up
deployedArtifacts.add(new File(remoteDirectory));
}
// copy deployment artifacts into the remote server
for (DeploymentArtifact artifactToDeploy : artifactsToDeploy) {
// acquire the source file to deploy
File sourceFile = artifactToDeploy.getSourceFile();
// change to the desired remote directory
File destinationFile = artifactToDeploy.getDestinationFile();
String destinationFileName;
if (destinationFile == null) {
sftpChannel.cd(remoteDirectory);
destinationFileName = sourceFile.getName();
// add the file as a deployed artifact
deployedArtifacts.add(new File(remoteDirectory, destinationFileName));
} else {
String destinationFilePath = separators.asPlatformFileName(destinationFile.getParent());
String dirName;
if (destinationFilePath == null) {
dirName = separators.asPlatformFileName(remoteDirectory);
} else {
dirName = separators.asPlatformFileName(destinationFilePath);
}
sftpChannel.cd(dirName);
destinationFileName = destinationFile.getName();
// add the file as a deployed artifact
deployedArtifacts.add(new File(dirName, destinationFileName));
}
// copy the source artifact to the destination file
double start = System.currentTimeMillis();
sftpChannel.put(new FileInputStream(sourceFile), destinationFileName);
double time = (System.currentTimeMillis() - start) / 1000.0d;
deploymentTable.addRow(sourceFile.toString(), String.valueOf(destinationFile), String.format("%.3f s", time));
}
Table diagnosticsTable = optionsByType.get(Table.class);
if (diagnosticsTable != null) {
diagnosticsTable.addRow("Application Deployments ", deploymentTable.toString());
}
} catch (IOException | SftpException e) {
throw new RuntimeException("Failed to deploy application", e);
} finally {
if (sftpChannel != null) {
sftpChannel.disconnect();
}
}
}
} catch (JSchException e) {
throw new RuntimeException("Failed to deploy application", e);
} finally {
if (session != null) {
session.disconnect();
}
}
return deployedArtifacts;
}
use of com.oracle.bedrock.table.Table in project oracle-bedrock by coherence-community.
the class FileShareDeployer method deploy.
@Override
public DeployedArtifacts deploy(List<DeploymentArtifact> artifactsToDeploy, String remoteDirectory, Platform platform, Option... deploymentOptions) {
DeployedArtifacts deployedArtifacts = new DeployedArtifacts();
OptionsByType combinedOptions = platform == null ? OptionsByType.empty() : OptionsByType.of(platform.getOptions());
Table deploymentTable = new Table();
combinedOptions.addAll(optionsByType);
combinedOptions.addAll(deploymentOptions);
PlatformSeparators separators = combinedOptions.get(PlatformSeparators.class);
File remoteShareFile = new File(remoteShareName);
for (DeploymentArtifact artifact : artifactsToDeploy) {
double start = System.currentTimeMillis();
try {
File sourceFile = artifact.getSourceFile();
Path localCopy = new File(localShareName, sourceFile.getName()).toPath();
Files.copy(artifact.getSourceFile().toPath(), localCopy, StandardCopyOption.REPLACE_EXISTING);
String destination;
String sourceName = artifact.getSourceFile().getName();
File destinationFile = artifact.getDestinationFile();
if (destinationFile == null) {
destination = remoteDirectory + separators.getFileSeparator() + sourceName;
} else {
String destinationFilePath = separators.asPlatformFileName(destinationFile.getParent());
String dirName;
if (destinationFilePath == null) {
dirName = separators.asPlatformFileName(remoteDirectory);
destination = dirName + separators.getFileSeparator() + destinationFile.getPath();
} else {
destination = separators.asPlatformFileName(destinationFile.getCanonicalPath());
}
}
String source = new File(remoteShareFile, sourceName).getCanonicalPath();
if (!source.equals(destination)) {
boolean cleanup = performRemoteCopy(source, destination, platform, combinedOptions);
if (cleanup) {
Files.delete(localCopy);
}
}
// add the file as a deployed artifact
deployedArtifacts.add(new File(destination));
double time = (System.currentTimeMillis() - start) / 1000.0d;
deploymentTable.addRow(sourceFile.toString(), String.valueOf(destination), String.format("%.3f s", time));
} catch (IOException e) {
throw new RuntimeException("Failed to deploy " + artifact, e);
}
}
Table diagnosticsTable = optionsByType.get(Table.class);
if (diagnosticsTable != null) {
diagnosticsTable.addRow("Application Deployments ", deploymentTable.toString());
}
return deployedArtifacts;
}
use of com.oracle.bedrock.table.Table in project oracle-bedrock by coherence-community.
the class RemoteJavaApplicationLauncher method getCommandToExecute.
@Override
public String getCommandToExecute(Platform platform, OptionsByType optionsByType) {
StringBuilder commandBuilder = new StringBuilder();
// ----- establish the command to start java -----
JavaHome javaHome = optionsByType.get(JavaHome.class);
// determine the Executable, defaulting to "java" if not defined
Executable executable = optionsByType.getOrSetDefault(Executable.class, Executable.named("java"));
if (javaHome == null) {
// when we don't have a java home we just use the defined executable
commandBuilder.append(StringHelper.doubleQuoteIfNecessary(executable.getName()));
} else {
// determine the PlatformSeparators (assume unix if not defined)
PlatformSeparators separators = optionsByType.getOrSetDefault(PlatformSeparators.class, PlatformSeparators.forUnix());
// when we have a java home, we prefix the executable name with the java.home/bin/
String javaHomePath = javaHome.get().trim();
String javaExecutable = javaHomePath;
if (!javaHomePath.endsWith(separators.getFileSeparator())) {
javaExecutable += separators.getFileSeparator();
}
javaExecutable += "bin";
javaExecutable += separators.getFileSeparator();
javaExecutable += executable.getName();
commandBuilder.append(StringHelper.doubleQuoteIfNecessary(javaExecutable));
Table diagnosticsTable = optionsByType.get(Table.class);
if (diagnosticsTable != null) {
diagnosticsTable.addRow("Java Home", javaHomePath);
diagnosticsTable.addRow("Java Executable", javaExecutable);
}
}
return commandBuilder.toString();
}
use of com.oracle.bedrock.table.Table in project oracle-bedrock by coherence-community.
the class JSchRemoteTerminal method launch.
@Override
public RemoteApplicationProcess launch(Launchable launchable, Class<? extends Application> applicationClass, OptionsByType optionsByType) {
// acquire the remote platform on which to launch the application
RemotePlatform platform = getRemotePlatform();
// establish a specialized SocketFactory for JSch
JSchSocketFactory socketFactory = new JSchSocketFactory();
// initially there's no session
Session session = null;
try {
// create the remote session
session = sessionFactory.createSession(platform.getAddress().getHostName(), platform.getPort(), platform.getUserName(), platform.getAuthentication(), socketFactory, optionsByType);
ChannelExec execChannel = (ChannelExec) session.openChannel("exec");
// (re)define the "local.address" variable so that we can use for resolving the platform
optionsByType.add(Variable.with("local.address", socketFactory.getLastLocalAddress().getHostAddress()));
// ----- establish the remote environment variables -----
String environmentVariables = "";
// get the remote environment variables for the remote application
Properties variables = launchable.getEnvironmentVariables(platform, optionsByType);
// determine the format to use for setting variables
String format;
Shell shell = optionsByType.getOrSetDefault(Shell.class, Shell.isUnknown());
switch(shell.getType()) {
case SH:
case BASH:
format = "export %s=%s ; ";
break;
case CSH:
case TSCH:
format = "setenv %s %s ; ";
break;
default:
// when we don't know, assume something bash-like
format = "export %s=%s ; ";
break;
}
List<String> arguments = launchable.getCommandLineArguments(platform, optionsByType);
CommandInterceptor interceptor = optionsByType.get(CommandInterceptor.class);
String executableName = launchable.getCommandToExecute(platform, optionsByType);
File workingDirectory = optionsByType.get(WorkingDirectory.class).resolve(platform, optionsByType);
String remoteCommand;
if (interceptor == null) {
for (String variableName : variables.stringPropertyNames()) {
environmentVariables += String.format(format, variableName, StringHelper.doubleQuoteIfNecessary(variables.getProperty(variableName)));
}
// ----- establish the application command line to execute -----
// determine the command to execute remotely
StringBuilder command = new StringBuilder(executableName);
// add the arguments
for (String arg : arguments) {
command.append(" ").append(arg);
}
// the actual remote command must include changing to the remote directory
remoteCommand = environmentVariables + String.format("cd %s ; %s", workingDirectory, command);
} else {
remoteCommand = interceptor.onExecute(executableName, arguments, variables, workingDirectory);
}
execChannel.setCommand(remoteCommand);
// ----- establish the remote application process to represent the remote application -----
// establish a RemoteApplicationProcess representing the remote application
RemoteApplicationProcess process = new JschRemoteApplicationProcess(session, execChannel);
if (optionsByType.get(LaunchLogging.class).isEnabled()) {
Table diagnosticsTable = optionsByType.get(Table.class);
if (diagnosticsTable != null && LOGGER.isLoggable(Level.INFO)) {
diagnosticsTable.addRow("Application Executable ", executableName);
LOGGER.log(Level.INFO, "Oracle Bedrock " + Bedrock.getVersion() + ": Starting Application...\n" + "------------------------------------------------------------------------\n" + diagnosticsTable.toString() + "\n" + "------------------------------------------------------------------------\n");
}
}
// connect the channel
execChannel.connect(session.getTimeout());
return process;
} catch (JSchException e) {
if (session != null) {
session.disconnect();
}
throw new RuntimeException("Failed to create remote application", e);
}
}
Aggregations