From c414e361e150c3a13041e780c4e1eb01825ca4f5 Mon Sep 17 00:00:00 2001 From: Tim Swast Date: Wed, 13 Apr 2016 16:26:42 -0700 Subject: [PATCH] Migrate sample from compute-getting-started-java repo. Only made minimal changes to follow style guide and update links. --- compute/cmdline/ComputeEngineSample.launch | 14 + compute/cmdline/README.md | 122 ++++++++ compute/cmdline/logging.properties | 10 + compute/cmdline/pom.xml | 95 ++++++ .../src/main/java/ComputeEngineSample.java | 272 ++++++++++++++++++ pom.xml | 1 + 6 files changed, 514 insertions(+) create mode 100644 compute/cmdline/ComputeEngineSample.launch create mode 100644 compute/cmdline/README.md create mode 100644 compute/cmdline/logging.properties create mode 100644 compute/cmdline/pom.xml create mode 100644 compute/cmdline/src/main/java/ComputeEngineSample.java diff --git a/compute/cmdline/ComputeEngineSample.launch b/compute/cmdline/ComputeEngineSample.launch new file mode 100644 index 00000000000..cee07bc5266 --- /dev/null +++ b/compute/cmdline/ComputeEngineSample.launch @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/compute/cmdline/README.md b/compute/cmdline/README.md new file mode 100644 index 00000000000..adaf3d67a8d --- /dev/null +++ b/compute/cmdline/README.md @@ -0,0 +1,122 @@ +# Compute Engine - Getting started with Java + +This sample command line application demonstrates how to access the Google +Compute Engine API using the Google Java API Client Library. + +When the sample is setup and run as instructed below, it will list all the +VM instances in a Google Cloud Platform project for a specific +[zone](https://cloud.google.com/compute/docs/zones). +The sample also checks for the existence of a VM instance named +"my-sample-instance". If the VM instance doesn't exist, the sample +will create a new VM instance named "my-sample-instance". If the VM instance +does exist, running the sample will delete the instance. The instance create +and delete actions are implemented as +"[zone specific operations](https://cloud.google.com/compute/docs/reference/latest/zoneOperations#resource)". +The sample demonstrates how to poll the status of these operations to +determine when and if they successfully complete. + +## Products +- [Compute Engine][1] + +## Language +- [Java][2] + +## APIs +- [Google Compute Engine][3] + +## Setup Instructions +1. Create or select a project in the Google Cloud Console: + 1. Visit the [Cloud Console][4] + 1. If this is your first time then click "Create Project," otherwise you can +reuse an existing project by clicking on it. + 1. Note: You will need to enable billing for the project to use Compute + Engine. + 1. Click "Overview" in the left-side navigation menu and copy your Project ID + for use in step 3.3 below. + +1. Authentication instructions to run the sample (on your local machine or on a Compute Engine VM): + * Running the sample locally on your development machine: + 1. Install [Google Cloud SDK](https://cloud.google.com/sdk/) + 1. Run the following command to authorize the Cloud SDK and configure your project: +
gcloud init
+ * Running the sample on a Google Compute Engine VM using Default Application + Credentials: + 1. Create a Compute Engine VM Instance. + 1. In the [Cloud Console](https://console.cloud.google.com/project) + go to the Compute > Compute Engine section. + 1. Click the "Create instance" button. + 1. For the 'Boot Disk' select a Linux machine image like Debian or Ubuntu. + 1. Click the "Management, disk, networking, access & security options" + section to expand it. + 1. Select the "Access and Security" subsection and then select the + "Compute" drop-down menu to set its scope. + * Set the "Compute" access scope to be "Read/Write". + 1. Click the "Create" button. + 1. Once the VM is created click the VM instance's "SSH" button to ssh + in to the newly created VM instance. + +1. Code checkout instructions: + 1. Prerequisites: install [Java 7 or Java 8 JDK][2], [Git][7], and [Maven][8]. +You may need to set your `JAVA_HOME` environment variable as well. + * To install these prerequisites on a Linux (Debian or Ubuntu) based Compute Engine VM + instance, run these commands: +
+    sudo apt-get update
+    sudo apt-get install git maven openjdk-7-jdk -y
+    
+ 1. Download the sample code by running the following commands: +
mkdir some_directory
+  cd some_directory
+  git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
+  cd java-docs-samples/compute/cmdline
+ In a text editor open the `ComputeEngineSample.java` file. For example, to edit the file with nano: +
nano src/main/java/ComputeEngineSample.java
+ + 1. In your text editor update the `YOUR_PROJECT_ID` value in + [`src/main/java/ComputeEngineSample.java`][5] +so that the following line is updated. Not performing this step will result +in an error; specifically, "Parameter 'project' must conform to the pattern...". +For more information see setting your [Project ID][6]. +
private static final String projectId = "YOUR_PROJECT_ID"
+ 1. Specify an 'Application Name' for your app by updating the following line of code: +
private static final String APPLICATION_NAME = "";
+ 1. Save the changes to the file and exit the text editor. + +1. Compile and run the sample: + 1. Compile the sample code using Maven by running the following command: +
mvn compile
+ 1. Execute the sample code using Maven by running the following command: +
mvn -q exec:java
+ 1. Running the sample will list all Google Compute Engine VM instances found in + the zone you specified. The sample will also check for the existence of a VM instance + named "my-sample-instance". If the "my-sample-instance" VM does not exist, running the + sample will create it. If the "my-sample-instance" VM does already exist then running the + sample will delete it. + + You can verify the list of VM instances by running the command + `gcloud compute instances list`. VM instances can be deleted with the 'gcloud compute instance delete' + command. For example, this command will delete the 'my-sample-instance' VM instance + in the zone 'us-central1-f': + + `gcloud compute instances delete my-sample-instance --zone us-central1-f` + +1. Importing the code into Eclipse and running it from there: + 1. Prerequisites: install [Eclipse][9] and the [Maven plugin for Eclipse][10]. + 1. Download code as specified above. + 1. File -> Import -> Maven -> Existing Maven Projects -> Next. + 1. Select your project directory as your "Root Directory," and click "Finish." + 1. Right-click on project compute-engine-cmdline-sample. + 1. Run As > Java Application. + 1. If asked, type or select "ComputeEngineSample" and click OK. + 1. Application output will display in the Eclipse Console. + +[1]: https://cloud.google.com/compute/ +[2]: http://java.com/en/download/faq/develop.xml +[3]: https://cloud.google.com/compute/ +[4]: https://console.cloud.google.com/project +[5]: https://github.com/GoogleCloudPlatform/java-docs-samples/blob/master/compute/cmdline/src/main/java/ComputeEngineSample.java#L54 +[6]: https://support.google.com/cloud/answer/6158840 +[7]: http://git-scm.com/downloads +[8]: http://maven.apache.org/download.html +[9]: http://www.eclipse.org/downloads/ +[10]: http://download.eclipse.org/technology/m2e/releases/ diff --git a/compute/cmdline/logging.properties b/compute/cmdline/logging.properties new file mode 100644 index 00000000000..40072d61c26 --- /dev/null +++ b/compute/cmdline/logging.properties @@ -0,0 +1,10 @@ +# Properties file which configures the operation of the JDK logging facility. +# The system will look for this config file to be specified as a system property: +# -Djava.util.logging.config.file=${project_loc:compute-engine-cmdline-sample}/logging.properties + +# Set up the console handler (uncomment "level" to show more fine-grained messages) +handlers = java.util.logging.ConsoleHandler +#java.util.logging.ConsoleHandler.level = CONFIG + +# Set up logging of HTTP requests and responses (uncomment "level" to show) +#com.google.api.client.http.level = CONFIG diff --git a/compute/cmdline/pom.xml b/compute/cmdline/pom.xml new file mode 100644 index 00000000000..5b12dd3d0ae --- /dev/null +++ b/compute/cmdline/pom.xml @@ -0,0 +1,95 @@ + + + 4.0.0 + com.google.cloud.samples + compute-cmdline + 1 + + + + com.google.cloud + doc-samples + 1.0.0 + ../.. + + + + + + maven-compiler-plugin + 3.5.1 + + 1.7 + 1.7 + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + + + java + + + + + ComputeEngineSample + + + java.util.logging.config.file + logging.properties + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.3 + + false + + + + + check + + + + + + ${project.artifactId}-${project.version} + + + + com.google.api-client + google-api-client + 1.21.0 + + + com.google.apis + google-api-services-compute + ${project.compute.version} + + + + v1-rev105-1.21.0 + UTF-8 + + diff --git a/compute/cmdline/src/main/java/ComputeEngineSample.java b/compute/cmdline/src/main/java/ComputeEngineSample.java new file mode 100644 index 00000000000..1a389e81392 --- /dev/null +++ b/compute/cmdline/src/main/java/ComputeEngineSample.java @@ -0,0 +1,272 @@ +/* + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed 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. + */ + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.compute.Compute; +import com.google.api.services.compute.ComputeScopes; +import com.google.api.services.compute.model.AccessConfig; +import com.google.api.services.compute.model.AttachedDisk; +import com.google.api.services.compute.model.AttachedDiskInitializeParams; +import com.google.api.services.compute.model.Instance; +import com.google.api.services.compute.model.InstanceList; +import com.google.api.services.compute.model.Metadata; +import com.google.api.services.compute.model.NetworkInterface; +import com.google.api.services.compute.model.Operation; +import com.google.api.services.compute.model.ServiceAccount; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Command-line sample to demo listing Google Compute Engine instances using Java and the Google + * Compute Engine API. + * + * @author Jonathan Simon + */ +public class ComputeEngineSample { + + /** + * Be sure to specify the name of your application. If the application name is {@code null} or + * blank, the application will log a warning. Suggested format is "MyCompany-ProductName/1.0". + */ + private static final String APPLICATION_NAME = ""; + + /** Set PROJECT_ID to your Project ID from the Overview pane in the Developers console. */ + private static final String PROJECT_ID = "YOUR_PROJECT_ID"; + + /** Set Compute Engine zone. */ + private static final String ZONE_NAME = "us-central1-f"; + + /** Set the name of the sample VM instance to be created. */ + private static final String SAMPLE_INSTANCE_NAME = "my-sample-instance"; + + /** Set the path of the OS image for the sample VM instance to be created. */ + private static final String SOURCE_IMAGE_PREFIX = "https://www.googleapis.com/compute/v1/projects/"; + private static final String SOURCE_IMAGE_PATH = + "debian-cloud/global/images/debian-7-wheezy-v20150710"; + + /** Set the Network configuration values of the sample VM instance to be created. */ + private static final String NETWORK_INTERFACE_CONFIG = "ONE_TO_ONE_NAT"; + private static final String NETWORK_ACCESS_CONFIG = "External NAT"; + + /** Set the time out limit for operation calls to the Compute Engine API. */ + private static final long OPERATION_TIMEOUT_MILLIS = 60 * 1000; + + /** Global instance of the HTTP transport. */ + private static HttpTransport httpTransport; + + /** Global instance of the JSON factory. */ + private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); + + + + public static void main(String[] args) { + try { + httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + + // Authenticate using Google Application Default Credentials. + GoogleCredential credential = GoogleCredential.getApplicationDefault(); + if (credential.createScopedRequired()) { + List scopes = new ArrayList<>(); + // Set Google Cloud Storage scope to Full Control. + scopes.add(ComputeScopes.DEVSTORAGE_FULL_CONTROL); + // Set Google Compute Engine scope to Read-write. + scopes.add(ComputeScopes.COMPUTE); + credential = credential.createScoped(scopes); + } + + // Create Compute Engine object for listing instances. + Compute compute = + new Compute.Builder(httpTransport, JSON_FACTORY, credential) + .setApplicationName(APPLICATION_NAME) + .build(); + + // List out instances, looking for the one created by this sample app. + boolean foundOurInstance = printInstances(compute); + + Operation op; + if (foundOurInstance) { + op = deleteInstance(compute, SAMPLE_INSTANCE_NAME); + } else { + op = startInstance(compute, SAMPLE_INSTANCE_NAME); + } + + // Call Compute Engine API operation and poll for operation completion status + System.out.println("Waiting for operation completion..."); + Operation.Error error = blockUntilComplete(compute, op, OPERATION_TIMEOUT_MILLIS); + if (error == null) { + System.out.println("Success!"); + } else { + System.out.println(error.toPrettyString()); + } + } catch (IOException e) { + System.err.println(e.getMessage()); + } catch (Throwable t) { + t.printStackTrace(); + } + System.exit(1); + } + + // [START list_instances] + /** + * Print available machine instances. + * + * @param compute The main API access point + * @return {@code true} if the instance created by this sample app is in the list + */ + public static boolean printInstances(Compute compute) throws IOException { + System.out.println("================== Listing Compute Engine Instances =================="); + Compute.Instances.List instances = compute.instances().list(PROJECT_ID, ZONE_NAME); + InstanceList list = instances.execute(); + boolean found = false; + if (list.getItems() == null) { + System.out.println("No instances found. Sign in to the Google Developers Console and create " + + "an instance at: https://console.developers.google.com/"); + } else { + for (Instance instance : list.getItems()) { + System.out.println(instance.toPrettyString()); + if (instance.getName().equals(SAMPLE_INSTANCE_NAME)) { + found = true; + } + } + } + return found; + } + // [END list_instances] + + // [START create_instances] + public static Operation startInstance(Compute compute, String instanceName) throws IOException { + System.out.println("================== Starting New Instance =================="); + + + // Create VM Instance object with the required properties. + Instance instance = new Instance(); + instance.setName(instanceName); + instance.setMachineType( + "https://www.googleapis.com/compute/v1/projects/" + + PROJECT_ID + "/zones/" + ZONE_NAME + "/machineTypes/n1-standard-1"); + + // Add Network Interface to be used by VM Instance. + NetworkInterface ifc = new NetworkInterface(); + ifc.setNetwork("https://www.googleapis.com/compute/v1/projects/" + PROJECT_ID + "/global/networks/default"); + List configs = new ArrayList<>(); + AccessConfig config = new AccessConfig(); + config.setType(NETWORK_INTERFACE_CONFIG); + config.setName(NETWORK_ACCESS_CONFIG); + configs.add(config); + ifc.setAccessConfigs(configs); + instance.setNetworkInterfaces(Collections.singletonList(ifc)); + + // Add attached Persistent Disk to be used by VM Instance. + AttachedDisk disk = new AttachedDisk(); + disk.setBoot(true); + disk.setAutoDelete(true); + disk.setType("PERSISTENT"); + AttachedDiskInitializeParams params = new AttachedDiskInitializeParams(); + // Assign the Persistent Disk the same name as the VM Instance. + params.setDiskName(instanceName); + // Specify the source operating system machine image to be used by the VM Instance. + params.setSourceImage(SOURCE_IMAGE_PREFIX + SOURCE_IMAGE_PATH); + // Specify the disk type as Standard Persistent Disk + params.setDiskType("https://www.googleapis.com/compute/v1/projects/" + PROJECT_ID + "/zones/" + + ZONE_NAME + "/diskTypes/pd-standard"); + disk.setInitializeParams(params); + instance.setDisks(Collections.singletonList(disk)); + + // Initialize the service account to be used by the VM Instance and set the API access scopes. + ServiceAccount account = new ServiceAccount(); + account.setEmail("default"); + List scopes = new ArrayList<>(); + scopes.add("https://www.googleapis.com/auth/devstorage.full_control"); + scopes.add("https://www.googleapis.com/auth/compute"); + account.setScopes(scopes); + instance.setServiceAccounts(Collections.singletonList(account)); + + // Optional - Add a startup script to be used by the VM Instance. + Metadata meta = new Metadata(); + Metadata.Items item = new Metadata.Items(); + item.setKey("startup-script-url"); + // If you put a script called "vm-startup.sh" in this Google Cloud Storage + // bucket, it will execute on VM startup. This assumes you've created a + // bucket named the same as your PROJECT_ID. + // For info on creating buckets see: https://cloud.google.com/storage/docs/cloud-console#_creatingbuckets + item.setValue("gs://" + PROJECT_ID + "/vm-startup.sh"); + meta.setItems(Collections.singletonList(item)); + instance.setMetadata(meta); + + System.out.println(instance.toPrettyString()); + Compute.Instances.Insert insert = compute.instances().insert(PROJECT_ID, ZONE_NAME, instance); + return insert.execute(); + } + // [END create_instances] + + private static Operation deleteInstance(Compute compute, String instanceName) throws Exception { + System.out.println( + "================== Deleting Instance " + instanceName + " =================="); + Compute.Instances.Delete delete = + compute.instances().delete(PROJECT_ID, ZONE_NAME, instanceName); + return delete.execute(); + } + + // [START wait_until_complete] + /** + * Wait until {@code operation} is completed. + * @param compute the {@code Compute} object + * @param operation the operation returned by the original request + * @param timeout the timeout, in millis + * @return the error, if any, else {@code null} if there was no error + * @throws InterruptedException if we timed out waiting for the operation to complete + * @throws IOException if we had trouble connecting + */ + public static Operation.Error blockUntilComplete( + Compute compute, Operation operation, long timeout) throws Exception { + long start = System.currentTimeMillis(); + final long pollInterval = 5 * 1000; + String zone = operation.getZone(); // null for global/regional operations + if (zone != null) { + String[] bits = zone.split("/"); + zone = bits[bits.length - 1]; + } + String status = operation.getStatus(); + String opId = operation.getName(); + while (operation != null && !status.equals("DONE")) { + Thread.sleep(pollInterval); + long elapsed = System.currentTimeMillis() - start; + if (elapsed >= timeout) { + throw new InterruptedException("Timed out waiting for operation to complete"); + } + System.out.println("waiting..."); + if (zone != null) { + Compute.ZoneOperations.Get get = compute.zoneOperations().get(PROJECT_ID, zone, opId); + operation = get.execute(); + } else { + Compute.GlobalOperations.Get get = compute.globalOperations().get(PROJECT_ID, opId); + operation = get.execute(); + } + if (operation != null) { + status = operation.getStatus(); + } + } + return operation == null ? null : operation.getError(); + } + // [END wait_until_complete] +} diff --git a/pom.xml b/pom.xml index d35d36bc8a0..64995cc1c52 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,7 @@ appengine/twilio appengine/urlfetch bigquery + compute/cmdline datastore logging managed_vms/analytics