From 7fd1c655752d88e682cc48b6a28d8d23f47a6aad Mon Sep 17 00:00:00 2001 From: Andrew Donald Kennedy Date: Thu, 7 Jun 2012 03:42:45 +0100 Subject: [PATCH] Issue 960: Add EC2 GetConsoleOutput API call --- .../ec2/services/InstanceAsyncClient.java | 11 ++++ .../jclouds/ec2/services/InstanceClient.java | 19 ++++++- .../xml/GetConsoleOutputResponseHandler.java | 53 +++++++++++++++++ .../ec2/services/InstanceAsyncClientTest.java | 18 ++++++ .../GetConsoleOutputResponseHandlerTest.java | 57 +++++++++++++++++++ .../resources/get_console_output_response.xml | 13 +++++ 6 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 apis/ec2/src/main/java/org/jclouds/ec2/xml/GetConsoleOutputResponseHandler.java create mode 100644 apis/ec2/src/test/java/org/jclouds/ec2/xml/GetConsoleOutputResponseHandlerTest.java create mode 100644 apis/ec2/src/test/resources/get_console_output_response.xml diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java index af5fd3af45..96d361e2e0 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java @@ -41,6 +41,7 @@ import org.jclouds.ec2.options.RunInstancesOptions; import org.jclouds.ec2.xml.BlockDeviceMappingHandler; import org.jclouds.ec2.xml.BooleanValueHandler; import org.jclouds.ec2.xml.DescribeInstancesResponseHandler; +import org.jclouds.ec2.xml.GetConsoleOutputResponseHandler; import org.jclouds.ec2.xml.InstanceInitiatedShutdownBehaviorHandler; import org.jclouds.ec2.xml.InstanceStateChangeHandler; import org.jclouds.ec2.xml.InstanceTypeHandler; @@ -323,4 +324,14 @@ public interface InstanceAsyncClient { @FormParam("InstanceId") String instanceId, @BinderParam(BindBlockDeviceMappingToIndexedFormParams.class) Map blockDeviceMapping); + /** + * @see InstanceClient#getConsoleOutputForInstanceInRegion(String, String) + */ + @POST + @Path("/") + @FormParams(keys = { ACTION }, values = { "GetConsoleOutput" }) + @XMLResponseParser(GetConsoleOutputResponseHandler.class) + ListenableFuture getConsoleOutputForInstanceInRegion( + @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, + @FormParam("InstanceId") String instanceId); } diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceClient.java index 4f9071e2bf..6c49f3815b 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceClient.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceClient.java @@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; import org.jclouds.ec2.domain.BlockDevice; -import org.jclouds.ec2.domain.InstanceState; import org.jclouds.ec2.domain.InstanceStateChange; import org.jclouds.ec2.domain.Reservation; import org.jclouds.ec2.domain.RunningInstance; @@ -573,4 +572,22 @@ public interface InstanceClient { */ void setBlockDeviceMappingForInstanceInRegion(@Nullable String region, String instanceId, Map blockDeviceMapping); + + /** + * Retrieves console output for the specified instance. + * + * Instance console output is buffered and posted shortly after instance boot, reboot, and termination. Amazon EC2 preserves + * the most recent 64 KB output which will be available for at least one hour after the most recent post. + * + * @param region + * Instances are tied to Availability Zones. However, the instance + * ID is tied to the Region. + * @param instanceId + * which instance to retrieve console output for + * @return The console output + * @see + * ApiReference query GetConsoleOutput + */ + String getConsoleOutputForInstanceInRegion(@Nullable String region, + String instanceId); } diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/GetConsoleOutputResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/GetConsoleOutputResponseHandler.java new file mode 100644 index 0000000000..631798d448 --- /dev/null +++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/GetConsoleOutputResponseHandler.java @@ -0,0 +1,53 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.ec2.xml; + +import org.jclouds.encryption.internal.Base64; +import org.jclouds.http.functions.ParseSax; + +import com.google.common.base.Charsets; + +/** + * @author Andrew Kennedy + * @see + * ApiReference query GetConsoleOutput + */ +public class GetConsoleOutputResponseHandler extends ParseSax.HandlerWithResult { + + private StringBuilder currentText = new StringBuilder(); + private String output; + + @Override + public String getResult() { + return output; + } + + @Override + public void endElement(String uri, String name, String qName) { + if (qName.equalsIgnoreCase("output")) { + this.output = new String(Base64.decode(currentText.toString().trim()), Charsets.UTF_8); + } + currentText = new StringBuilder(); + } + + @Override + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java index 96d00c6888..ac0b44c907 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java @@ -30,6 +30,7 @@ import org.jclouds.ec2.options.RunInstancesOptions; import org.jclouds.ec2.xml.BlockDeviceMappingHandler; import org.jclouds.ec2.xml.BooleanValueHandler; import org.jclouds.ec2.xml.DescribeInstancesResponseHandler; +import org.jclouds.ec2.xml.GetConsoleOutputResponseHandler; import org.jclouds.ec2.xml.InstanceInitiatedShutdownBehaviorHandler; import org.jclouds.ec2.xml.InstanceStateChangeHandler; import org.jclouds.ec2.xml.InstanceTypeHandler; @@ -488,6 +489,23 @@ public class InstanceAsyncClientTest extends BaseEC2AsyncClientTest> createTypeLiteral() { return new TypeLiteral>() { diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/xml/GetConsoleOutputResponseHandlerTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/xml/GetConsoleOutputResponseHandlerTest.java new file mode 100644 index 0000000000..a2d7236c58 --- /dev/null +++ b/apis/ec2/src/test/java/org/jclouds/ec2/xml/GetConsoleOutputResponseHandlerTest.java @@ -0,0 +1,57 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.ec2.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; + +import org.jclouds.http.functions.BaseHandlerTest; +import org.testng.annotations.Test; + +/** + * Tests behavior of {@code GetConsoleOutputResponseHandler} + * + * @author Andrew Kennedy + */ +//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "GetConsoleOutputResponseHandlerTest") +public class GetConsoleOutputResponseHandlerTest extends BaseHandlerTest { + public void testApplyInputStream() { + + InputStream is = getClass().getResourceAsStream( + "/get_console_output_response.xml"); + + String result = factory.create( + injector.getInstance(GetConsoleOutputResponseHandler.class)).parse(is); + + String expected = "Linux version 2.6.16-xenU (builder@patchbat.amazonsa) (gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)) #1 SMP Thu Oct 26 08:41:26 SAST 2006\n" + + "BIOS-provided physical RAM map:\n" + + "Xen: 0000000000000000 - 000000006a400000 (usable)\n" + + "980MB HIGHMEM available.\n" + + "727MB LOWMEM available.\n" + + "NX (Execute Disable) protection: active\n" + + "IRQ lockup detection disabled\n" + + "Built 1 zonelists\n" + + "Kernel command line: root=/dev/sda1 ro 4\n" + + "Enabling fast FPU save and restore... done.\n"; + + assertEquals(result, expected); + } +} diff --git a/apis/ec2/src/test/resources/get_console_output_response.xml b/apis/ec2/src/test/resources/get_console_output_response.xml new file mode 100644 index 0000000000..caf3ac9fd1 --- /dev/null +++ b/apis/ec2/src/test/resources/get_console_output_response.xml @@ -0,0 +1,13 @@ + + 59dbff89-35bd-4eac-99ed-be587EXAMPLE + i-28a64341 + 2010-10-14T01:12:41.000Z + TGludXggdmVyc2lvbiAyLjYuMTYteGVuVSAoYnVpbGRlckBwYXRjaGJhdC5hbWF6b25zYSkgKGdj +YyB2ZXJzaW9uIDQuMC4xIDIwMDUwNzI3IChSZWQgSGF0IDQuMC4xLTUpKSAjMSBTTVAgVGh1IE9j +dCAyNiAwODo0MToyNiBTQVNUIDIwMDYKQklPUy1wcm92aWRlZCBwaHlzaWNhbCBSQU0gbWFwOgpY +ZW46IDAwMDAwMDAwMDAwMDAwMDAgLSAwMDAwMDAwMDZhNDAwMDAwICh1c2FibGUpCjk4ME1CIEhJ +R0hNRU0gYXZhaWxhYmxlLgo3MjdNQiBMT1dNRU0gYXZhaWxhYmxlLgpOWCAoRXhlY3V0ZSBEaXNh +YmxlKSBwcm90ZWN0aW9uOiBhY3RpdmUKSVJRIGxvY2t1cCBkZXRlY3Rpb24gZGlzYWJsZWQKQnVp +bHQgMSB6b25lbGlzdHMKS2VybmVsIGNvbW1hbmQgbGluZTogcm9vdD0vZGV2L3NkYTEgcm8gNApF +bmFibGluZyBmYXN0IEZQVSBzYXZlIGFuZCByZXN0b3JlLi4uIGRvbmUuCg== + \ No newline at end of file