From f69518b752de5b96e910651c54be4e6c58bbe256 Mon Sep 17 00:00:00 2001 From: Irmo Manie Date: Tue, 1 Sep 2015 11:35:44 +0200 Subject: [PATCH] JCLOUDS-993 - Add missing parameters to `VirtualMachineApi` - `serviceOfferingId` at `#changeServiceForVirtualMachine` - `options` of type `UpdateVirtualMachineOptions` at `#updateVirtualMachine` --- .../features/VirtualMachineApi.java | 9 +- .../options/UpdateVirtualMachineOptions.java | 130 ++++++++++++++++++ .../features/VirtualMachineApiLiveTest.java | 10 ++ .../features/VirtualMachineApiTest.java | 26 +++- 4 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateVirtualMachineOptions.java diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VirtualMachineApi.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VirtualMachineApi.java index 413bfc5f8b..f98ee9d051 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VirtualMachineApi.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VirtualMachineApi.java @@ -32,6 +32,7 @@ import org.jclouds.cloudstack.filters.AuthenticationFilter; import org.jclouds.cloudstack.options.AssignVirtualMachineOptions; import org.jclouds.cloudstack.options.DeployVirtualMachineOptions; import org.jclouds.cloudstack.options.ListVirtualMachinesOptions; +import org.jclouds.cloudstack.options.UpdateVirtualMachineOptions; import org.jclouds.cloudstack.options.StopVirtualMachineOptions; import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.OnlyElement; @@ -198,6 +199,8 @@ public interface VirtualMachineApi { * * @param id * The ID of the virtual machine + * @param serviceOfferingId + * The service offering ID to apply to the virtual machine * @return job id related to destroying the VM */ @Named("changeServiceForVirtualMachine") @@ -205,7 +208,8 @@ public interface VirtualMachineApi { @QueryParams(keys = "command", values = "changeServiceForVirtualMachine") @SelectJson("jobid") @Consumes(MediaType.APPLICATION_JSON) - String changeServiceForVirtualMachine(@QueryParam("id") String id); + String changeServiceForVirtualMachine(@QueryParam("id") String id, + @QueryParam("serviceofferingid") String serviceOfferingId); /** * Updates parameters of a virtual machine. @@ -219,7 +223,8 @@ public interface VirtualMachineApi { @QueryParams(keys = "command", values = "updateVirtualMachine") @SelectJson("jobid") @Consumes(MediaType.APPLICATION_JSON) - String updateVirtualMachine(@QueryParam("id") String id); + String updateVirtualMachine(@QueryParam("id") String id, + UpdateVirtualMachineOptions options); /** * Destroys a virtual machine. Once destroyed, only the administrator can diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateVirtualMachineOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateVirtualMachineOptions.java new file mode 100644 index 0000000000..591a6a3b26 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateVirtualMachineOptions.java @@ -0,0 +1,130 @@ +/* + * 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.cloudstack.options; + +import com.google.common.collect.ImmutableSet; +import org.jclouds.http.options.BaseHttpRequestOptions; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.io.BaseEncoding.base64; + +/** + * Options for updating virtual machines. + * + * @see + */ +public class UpdateVirtualMachineOptions extends BaseHttpRequestOptions { + + public static final UpdateVirtualMachineOptions NONE = new UpdateVirtualMachineOptions(); + + /** + * sets the displayName - just for display purposes. We don't pass this + * parameter to the backend. + * + * @param displayName an optional user generated name for the virtual machine + */ + public UpdateVirtualMachineOptions displayName(String displayName) { + this.queryParameters.replaceValues("displayname", ImmutableSet.of(displayName)); + return this; + } + + /** + * @param group an optional group for the virtual machine + */ + public UpdateVirtualMachineOptions group(String group) { + this.queryParameters.replaceValues("group", ImmutableSet.of(group)); + return this; + } + + /** + * @param haEnable true if high-availability is enabled for the virtual machine, false otherwise + */ + public UpdateVirtualMachineOptions haEnable(boolean haEnable) { + this.queryParameters.replaceValues("haenable", ImmutableSet.of(String.valueOf(haEnable))); + return this; + } + + /** + * @param osTypeId the ID of the OS type that best represents this VM. + */ + public UpdateVirtualMachineOptions osTypeId(String osTypeId) { + this.queryParameters.replaceValues("ostypeid", ImmutableSet.of(String.valueOf(osTypeId))); + return this; + } + + /** + * @param unencodedData an optional binary data that can be sent to the virtual machine + * upon a successful deployment. This binary data must be base64 + * encoded before adding it to the request. Currently only HTTP GET + * is supported. Using HTTP GET (via querystring), you can send up + * to 2KB of data after base64 encoding. + */ + public UpdateVirtualMachineOptions userData(byte[] unencodedData) { + int length = checkNotNull(unencodedData, "unencodedData").length; + checkArgument(length > 0, "userData cannot be empty"); + checkArgument(length <= 2 * 1024, "userData cannot be larger than 2kb"); + this.queryParameters.replaceValues("userdata", ImmutableSet.of(base64().encode(unencodedData))); + return this; + } + + + public static class Builder { + + /** + * @see UpdateVirtualMachineOptions#displayName + */ + public static UpdateVirtualMachineOptions displayName(String displayName) { + UpdateVirtualMachineOptions options = new UpdateVirtualMachineOptions(); + return options.displayName(displayName); + } + + /** + * @see UpdateVirtualMachineOptions#group + */ + public static UpdateVirtualMachineOptions group(String group) { + UpdateVirtualMachineOptions options = new UpdateVirtualMachineOptions(); + return options.group(group); + } + + /** + * @see UpdateVirtualMachineOptions#haEnable + */ + public static UpdateVirtualMachineOptions haEnable(boolean haEnable) { + UpdateVirtualMachineOptions options = new UpdateVirtualMachineOptions(); + return options.haEnable(haEnable); + } + + /** + * @see UpdateVirtualMachineOptions#osTypeId + */ + public static UpdateVirtualMachineOptions osTypeId(String osTypeId) { + UpdateVirtualMachineOptions options = new UpdateVirtualMachineOptions(); + return options.osTypeId(osTypeId); + } + + /** + * @see UpdateVirtualMachineOptions#userData + */ + public static UpdateVirtualMachineOptions userData(byte[] unencodedData) { + UpdateVirtualMachineOptions options = new UpdateVirtualMachineOptions(); + return options.userData(unencodedData); + } + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiLiveTest.java index 2ca160c526..600eb1842e 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiLiveTest.java @@ -46,6 +46,7 @@ import org.jclouds.cloudstack.domain.Zone; import org.jclouds.cloudstack.internal.BaseCloudStackApiLiveTest; import org.jclouds.cloudstack.options.CreateNetworkOptions; import org.jclouds.cloudstack.options.DeployVirtualMachineOptions; +import org.jclouds.cloudstack.options.UpdateVirtualMachineOptions; import org.jclouds.cloudstack.options.ListNetworkOfferingsOptions; import org.jclouds.cloudstack.options.ListNetworksOptions; import org.jclouds.cloudstack.options.ListTemplatesOptions; @@ -320,6 +321,15 @@ public class VirtualMachineApiLiveTest extends BaseCloudStackApiLiveTest { assertEquals(vm.getState(), VirtualMachine.State.RUNNING); } + @Test(dependsOnMethods = "testCreateVirtualMachine") + public void testVirtualMachineUpdate() throws Exception { + UpdateVirtualMachineOptions options = UpdateVirtualMachineOptions.Builder.displayName("updated-name"); + String job = client.getVirtualMachineApi().updateVirtualMachine(vm.getId(), options); + assertTrue(jobComplete.apply(job)); + vm = client.getVirtualMachineApi().getVirtualMachine(vm.getId()); + assertEquals(vm.getDisplayName(), "updated-name"); + } + @AfterGroups(groups = "live") @Override protected void tearDownContext() { diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiTest.java index c06c08bebf..e95607496c 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineApiTest.java @@ -19,9 +19,12 @@ package org.jclouds.cloudstack.features; import static org.jclouds.reflect.Reflection2.method; import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.Charset; import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; +import org.jclouds.cloudstack.options.UpdateVirtualMachineOptions; import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions; import org.jclouds.cloudstack.internal.BaseCloudStackApiTest; import org.jclouds.cloudstack.options.AssignVirtualMachineOptions; @@ -35,6 +38,7 @@ import org.testng.annotations.Test; import com.google.common.base.Functions; import com.google.common.collect.ImmutableList; import com.google.common.reflect.Invokable; +import static com.google.common.io.BaseEncoding.base64; /** * Tests behavior of {@code VirtualMachineApi} */ @@ -187,11 +191,11 @@ public class VirtualMachineApiTest extends BaseCloudStackApiTest method = method(VirtualMachineApi.class, "changeServiceForVirtualMachine", String.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList. of(5)); + Invokable method = method(VirtualMachineApi.class, "changeServiceForVirtualMachine", String.class, String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList. of(5, 6)); assertRequestLineEquals(httpRequest, - "GET http://localhost:8080/client/api?response=json&command=changeServiceForVirtualMachine&id=5 HTTP/1.1"); + "GET http://localhost:8080/client/api?response=json&command=changeServiceForVirtualMachine&id=5&serviceofferingid=6 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); assertPayloadEquals(httpRequest, null, null, false); @@ -204,11 +208,21 @@ public class VirtualMachineApiTest extends BaseCloudStackApiTest method = method(VirtualMachineApi.class, "updateVirtualMachine", String.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList. of(5)); + Invokable method = method(VirtualMachineApi.class, "updateVirtualMachine", String.class, + UpdateVirtualMachineOptions.class); + byte[] unencodedData = "userData".getBytes(Charset.forName("utf-8")); + UpdateVirtualMachineOptions options = UpdateVirtualMachineOptions.Builder + .displayName("disp").group("test").haEnable(true).osTypeId("osid").userData(unencodedData); + GeneratedHttpRequest httpRequest = processor.createRequest(method, ImmutableList. of("5", + options)); + + + String base64UrlEncodedData = URLEncoder.encode(base64().encode(unencodedData), "utf-8"); assertRequestLineEquals(httpRequest, - "GET http://localhost:8080/client/api?response=json&command=updateVirtualMachine&id=5 HTTP/1.1"); + "GET http://localhost:8080/client/api?response=json&command=updateVirtualMachine" + + "&id=5&displayname=disp&group=test&haenable=true&ostypeid=osid&userdata=" + + base64UrlEncodedData + " HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); assertPayloadEquals(httpRequest, null, null, false);