Repository: jclouds-examples Updated Branches: refs/heads/master faeb71af4 -> 276f6caa0
Adding an example to run a simple program on a GCE VM. Project: http://git-wip-us.apache.org/repos/asf/jclouds-examples/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-examples/commit/276f6caa Tree: http://git-wip-us.apache.org/repos/asf/jclouds-examples/tree/276f6caa Diff: http://git-wip-us.apache.org/repos/asf/jclouds-examples/diff/276f6caa Branch: refs/heads/master Commit: 276f6caa0e975ee0af8ca206de1da5524d0e92a8 Parents: faeb71a Author: Marek Wieczorek <[email protected]> Authored: Wed Jul 30 13:04:30 2014 +0200 Committer: Andrew Phillips <[email protected]> Committed: Mon Aug 4 11:28:52 2014 +0200 ---------------------------------------------------------------------- .../google/computeengine/ExecuteCommand.java | 164 +++++++++++++++++++ 1 file changed, 164 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-examples/blob/276f6caa/google/src/main/java/org/jclouds/examples/google/computeengine/ExecuteCommand.java ---------------------------------------------------------------------- diff --git a/google/src/main/java/org/jclouds/examples/google/computeengine/ExecuteCommand.java b/google/src/main/java/org/jclouds/examples/google/computeengine/ExecuteCommand.java new file mode 100644 index 0000000..888ebdf --- /dev/null +++ b/google/src/main/java/org/jclouds/examples/google/computeengine/ExecuteCommand.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.examples.google.computeengine; + +import static org.jclouds.compute.config.ComputeServiceProperties.POLL_INITIAL_PERIOD; +import static org.jclouds.compute.config.ComputeServiceProperties.POLL_MAX_PERIOD; +import static org.jclouds.compute.options.TemplateOptions.Builder.overrideLoginCredentials; +import static org.jclouds.examples.google.computeengine.Constants.POLL_PERIOD_TWENTY_SECONDS; +import static org.jclouds.examples.google.computeengine.Constants.PROVIDER; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Properties; +import java.util.concurrent.TimeoutException; + +import org.jclouds.ContextBuilder; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.RunNodesException; +import org.jclouds.compute.domain.ExecResponse; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.options.RunScriptOptions; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.scriptbuilder.domain.Statement; +import org.jclouds.scriptbuilder.domain.Statements; +import org.jclouds.sshj.config.SshjSshClientModule; + +import com.google.common.collect.ImmutableSet; +import com.google.common.io.Closeables; +import com.google.common.io.Files; +import com.google.inject.Module; + +/** + * This example connects to an existing VM and runs a simple program (/bin/ls) on it. + */ +public class ExecuteCommand implements Closeable { + private final ComputeService computeService; + + /** + * Prerequisites: + * - service account created and its private key available on the local machine (see README.txt). + * - a VM created and SSH access enabled. + * + * The first argument (args[0]) is your service account email address + * (https://developers.google.com/console/help/new/#serviceaccounts). + * The second argument (args[1]) is a path to your service account private key PEM file without a password + * (https://developers.google.com/console/help/new/#serviceaccounts). + * The third argument (args[2]) is the name of your instance + * (https://developers.google.com/compute/docs/instances#start_vm). + * The fourth argument (args[3]) is the zone where your instance is located + * (https://developers.google.com/compute/docs/zones). + * The fifth argument (args[4]) is your Google user name. + * The sixth argument (args[5]) is a path to the file containing your SSH private key + * (https://developers.google.com/compute/docs/instances#sshkeys). + * + * Example: + * + * java org.jclouds.examples.google.computeengine.ExecuteCommand \ + * [email protected] \ + * /home/planetnik/Work/Cloud/OSS/certificate/gcp-oss.pem \ + * planetnik-main \ + * europe-west1-a \ + * planetnik \ + * /home/planetnik/.ssh/google_compute_engine + */ + public static void main(final String[] args) throws IOException { + String serviceAccountEmailAddress = args[0]; + String serviceAccountKey = Files.toString(new File(args[1]), Charset.defaultCharset()); + String instanceName = args[2]; + String zone = args[3]; + String googleUserName = args[4]; + String sshPrivateKey = Files.toString(new File(args[5]), Charset.defaultCharset()); + + ExecuteCommand executeApplication = new ExecuteCommand(serviceAccountEmailAddress, serviceAccountKey); + + try { + NodeMetadata instance = executeApplication.locateInstance(instanceName, zone); + if (instance != null) { + String publicAddress = instance.getPublicAddresses().iterator().next(); + System.out.format("Instance %s found with IP %s%n", instance.getName(), publicAddress); + } else { + System.err.format("Error: Instance %s could not be located in zone %s.%n", instanceName, zone); + System.exit(1); + } + executeApplication.executeSimpleCommand(instance, googleUserName, sshPrivateKey); + } catch (Exception e) { + e.printStackTrace(); + } finally { + executeApplication.close(); + } + } + + public ExecuteCommand(final String serviceAccountEmailAddress, final String serviceAccountKey) { + // These properties control how often jclouds polls for a status update. + Properties overrides = new Properties(); + overrides.setProperty(POLL_INITIAL_PERIOD, POLL_PERIOD_TWENTY_SECONDS); + overrides.setProperty(POLL_MAX_PERIOD, POLL_PERIOD_TWENTY_SECONDS); + + Iterable<Module> modules = ImmutableSet.<Module> of(new SshjSshClientModule()); + + ComputeServiceContext context = ContextBuilder.newBuilder(PROVIDER) + .credentials(serviceAccountEmailAddress, serviceAccountKey) + .modules(modules) + .overrides(overrides) + .buildView(ComputeServiceContext.class); + computeService = context.getComputeService(); + } + + private NodeMetadata locateInstance(final String instanceName, final String zone) + throws RunNodesException, TimeoutException { + System.out.format("Locating instance: %s%n", zone + "/" + instanceName); + + NodeMetadata instance = computeService.getNodeMetadata(zone + "/" + instanceName); + + return instance; + } + + private void executeSimpleCommand( + final NodeMetadata instance, final String googleUserName, final String sshPrivateKey) { + Statement script = Statements.exec("ls -l /"); + + // Set up credentials. + RunScriptOptions options = overrideLoginCredentials((new LoginCredentials.Builder()) + .user(googleUserName) + .privateKey(sshPrivateKey) + .build()) + .blockOnComplete(true) + .runAsRoot(false); + + ExecResponse response = computeService.runScriptOnNode(instance.getId(), script, options); + + System.out.format("Exit Status:%n============%n%s%n%n", response.getExitStatus()); + if (response.getExitStatus() == 0) { + System.out.format("Output:%n======%n%s%n%n", response.getOutput()); + } else { + System.out.format("Error:%n======%n%s%n%n", response.getError()); + } + } + + /** + * Always close your service when you're done with it. + */ + public final void close() throws IOException { + Closeables.close(computeService.getContext(), true); + } +}
