Repository: jclouds Updated Branches: refs/heads/1.7.x c368bae28 -> a38cbd580
Better documentation and a bugfix for cloud-init Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/a38cbd58 Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/a38cbd58 Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/a38cbd58 Branch: refs/heads/1.7.x Commit: a38cbd5803b0d6b35875eb0d951ac32466fa9bd4 Parents: c368bae Author: Zack Shoylev <[email protected]> Authored: Fri Feb 28 11:02:33 2014 -0600 Committer: Zack Shoylev <[email protected]> Committed: Mon Mar 3 18:57:01 2014 -0600 ---------------------------------------------------------------------- .../v2_0/compute/NovaComputeServiceAdapter.java | 1 + .../compute/options/NovaTemplateOptions.java | 73 ++++++++++++++------ .../nova/v2_0/options/CreateServerOptions.java | 23 +++++- .../NovaComputeServiceAdapterExpectTest.java | 34 +++++++++ .../options/NovaTemplateOptionsTest.java | 2 +- .../test/resources/new_server_config_drive.json | 42 +++++++++++ .../src/test/resources/server_details.json | 2 +- 7 files changed, 153 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38cbd58/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapter.java ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapter.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapter.java index 85bd640..0241c17 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapter.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapter.java @@ -109,6 +109,7 @@ public class NovaComputeServiceAdapter implements options.securityGroupNames(templateOptions.getSecurityGroupNames().get()); options.userData(templateOptions.getUserData()); options.diskConfig(templateOptions.getDiskConfig()); + options.configDrive(templateOptions.getConfigDrive()); options.networks(templateOptions.getNetworks()); Optional<String> privateKey = Optional.absent(); http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38cbd58/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java index aeb806f..d82d901 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java @@ -69,11 +69,13 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { eTo.generateKeyPair(shouldGenerateKeyPair()); eTo.keyPairName(getKeyPairName()); if (getUserData() != null) { - eTo.userData(getUserData()); + eTo.userData(getUserData()); } if (getDiskConfig() != null) { eTo.diskConfig(getDiskConfig()); - } + } + + eTo.configDrive(getConfigDrive()); } } @@ -83,6 +85,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { protected String keyPairName; protected byte[] userData; protected String diskConfig; + protected boolean configDrive; @Override public boolean equals(Object o) { @@ -96,12 +99,13 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { && equal(this.generateKeyPair, that.generateKeyPair) && equal(this.keyPairName, that.keyPairName) && Arrays.equals(this.userData, that.userData) - && equal(this.diskConfig, that.diskConfig); + && equal(this.diskConfig, that.diskConfig) + && equal(this.configDrive, that.configDrive); } @Override public int hashCode() { - return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, securityGroupNames, generateKeyPair, keyPairName, userData, diskConfig); + return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, securityGroupNames, generateKeyPair, keyPairName, userData, diskConfig, configDrive); } @Override @@ -116,6 +120,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { toString.add("keyPairName", keyPairName); toString.add("userData", userData); toString.add("diskConfig", diskConfig); + toString.add("configDrive", configDrive); return toString; } @@ -182,7 +187,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { public String getKeyPairName() { return keyPairName; } - + /** * <h3>Note</h3> * @@ -194,7 +199,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { public boolean shouldGenerateKeyPair() { return generateKeyPair; } - + /** * if unset, generate a default group prefixed with {@link jclouds#} according * to {@link #getInboundPorts()} @@ -206,15 +211,22 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { } public byte[] getUserData() { - return userData; - } + return userData; + } /** * @see CreateServerOptions#getDiskConfig() */ public String getDiskConfig() { - return diskConfig; - } + return diskConfig; + } + + /** + * @see CreateServerOptions#getConfigDrive() + */ + public boolean getConfigDrive() { + return configDrive; + } public static class Builder { @@ -238,7 +250,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { public static NovaTemplateOptions keyPairName(String keyPairName) { return new NovaTemplateOptions().keyPairName(keyPairName); } - + /** * @see org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getSecurityGroupNames */ @@ -352,7 +364,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { NovaTemplateOptions options = new NovaTemplateOptions(); return options.overrideLoginCredentials(credentials); } - + /** * @see TemplateOptions#blockUntilRunning */ @@ -360,7 +372,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { NovaTemplateOptions options = new NovaTemplateOptions(); return options.blockUntilRunning(blockUntilRunning); } - + /** * @see NovaTemplateOptions#userData */ @@ -368,7 +380,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { NovaTemplateOptions options = new NovaTemplateOptions(); return NovaTemplateOptions.class.cast(options.userData(userData)); } - + /** * @see org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getDiskConfig() */ @@ -376,6 +388,14 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { NovaTemplateOptions options = new NovaTemplateOptions(); return NovaTemplateOptions.class.cast(options.diskConfig(diskConfig)); } + + /** + * @see org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getConfigDrive() + */ + public static NovaTemplateOptions configDrive(boolean configDrive) { + NovaTemplateOptions options = new NovaTemplateOptions(); + return NovaTemplateOptions.class.cast(options.configDrive(configDrive)); + } } // methods that only facilitate returning the correct object type @@ -528,11 +548,11 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { * User data as bytes (not base64-encoded) */ public NovaTemplateOptions userData(byte[] userData) { - // This limit may not be needed for nova - checkArgument(checkNotNull(userData, "userData").length <= 16 * 1024, - "userData cannot be larger than 16kb"); - this.userData = userData; - return this; + // This limit may not be needed for nova + checkArgument(checkNotNull(userData, "userData").length <= 16 * 1024, + "userData cannot be larger than 16kb"); + this.userData = userData; + return this; } /** @@ -541,5 +561,18 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable { public NovaTemplateOptions diskConfig(String diskConfig) { this.diskConfig = diskConfig; return this; - } + } + + /** + * OpenStack can be configured to write metadata to a special configuration drive that will be + * attached to the instance when it boots. The instance can retrieve any information that would + * normally be available through the metadata service by mounting this disk and reading files from it. + * To enable the config drive, set this parameter to "true". + * This has to be enabled for user data cases. + * @see CreateServerOptions#getConfigDrive() + */ + public NovaTemplateOptions configDrive(boolean configDrive) { + this.configDrive = configDrive; + return this; + } } http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38cbd58/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java index e55b893..ce88ae5 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/options/CreateServerOptions.java @@ -107,6 +107,7 @@ public class CreateServerOptions implements MapBinder { private String diskConfig; private Set<String> networks = ImmutableSet.of(); private String availabilityZone; + private boolean configDrive; @Override public boolean equals(Object object) { @@ -119,7 +120,8 @@ public class CreateServerOptions implements MapBinder { && equal(metadata, other.metadata) && equal(personality, other.personality) && equal(adminPass, other.adminPass) && equal(diskConfig, other.diskConfig) && equal(adminPass, other.adminPass) && equal(networks, other.networks) - && equal(availabilityZone, other.availabilityZone); + && equal(availabilityZone, other.availabilityZone) + && equal(configDrive, other.configDrive); } else { return false; } @@ -127,7 +129,7 @@ public class CreateServerOptions implements MapBinder { @Override public int hashCode() { - return Objects.hashCode(keyName, securityGroupNames, metadata, personality, adminPass, networks, availabilityZone); + return Objects.hashCode(keyName, securityGroupNames, metadata, personality, adminPass, networks, availabilityZone, configDrive); } protected ToStringHelper string() { @@ -147,6 +149,7 @@ public class CreateServerOptions implements MapBinder { if (!networks.isEmpty()) toString.add("networks", networks); toString.add("availability_zone", availabilityZone == null ? null : availabilityZone); + toString.add("configDrive", configDrive); return toString; } @@ -171,6 +174,8 @@ public class CreateServerOptions implements MapBinder { @Named("OS-DCF:diskConfig") String diskConfig; Set<Map<String, String>> networks; + @Named("config_drive") + String configDrive; private ServerRequest(String name, String imageRef, String flavorRef) { this.name = name; @@ -195,6 +200,8 @@ public class CreateServerOptions implements MapBinder { server.availabilityZone = availabilityZone; if (userData != null) server.user_data = base64().encode(userData); + if (configDrive == true) + server.configDrive = "true"; if (securityGroupNames.size() > 0) { server.securityGroupNames = Sets.newLinkedHashSet(); for (String groupName : securityGroupNames) { @@ -290,6 +297,7 @@ public class CreateServerOptions implements MapBinder { * Custom user-data can be also be supplied at launch time. * It is retrievable by the instance and is often used for launch-time configuration * by instance scripts. + * Pass userData unencdoed, as the value will be base64 encoded automatically. */ public CreateServerOptions userData(byte[] userData) { this.userData = userData; @@ -297,6 +305,17 @@ public class CreateServerOptions implements MapBinder { } /** + * Set to true to use a config drive for metadata. + * This is a separate configuration drive that can be used separately from the metadata service. + * This needs to be set to "true" when trying to use user data for cloud-init. + * @see http://docs.openstack.org/grizzly/openstack-compute/admin/content/config-drive.html + */ + public CreateServerOptions configDrive(boolean configDrive) { + this.configDrive = configDrive; + return this; + } + + /** * A keypair name can be defined when creating a server. This key will be * linked to the server and used to SSH connect to the machine */ http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38cbd58/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapterExpectTest.java ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapterExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapterExpectTest.java index c48c434..52190cb 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapterExpectTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceAdapterExpectTest.java @@ -131,6 +131,40 @@ public class NovaComputeServiceAdapterExpectTest extends BaseNovaComputeServiceC assertEquals(server.getNode().getServer().getDiskConfig().orNull(), Server.DISK_CONFIG_AUTO); } + public void testCreateNodeWithGroupEncodedIntoNameWithConfigDrive() throws Exception { + + HttpRequest createServer = HttpRequest + .builder() + .method("POST") + .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers") + .addHeader("Accept", "application/json") + .addHeader("X-Auth-Token", authToken) + .payload(payloadFromStringWithContentType( + "{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"config_drive\":\"true\"}}","application/json")) + .build(); + + HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted") + .payload(payloadFromResourceWithContentType("/new_server_config_drive.json","application/json; charset=UTF-8")).build(); + + Map<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder() + .put(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess) + .put(extensionsOfNovaRequest, extensionsOfNovaResponse) + .put(listDetail, listDetailResponse) + .put(listFlavorsDetail, listFlavorsDetailResponse) + .put(createServer, createServerResponse) + .put(serverDetail, serverDetailResponse).build(); + + Injector forConfigDrive = requestsSendResponses(requestResponseMap); + + Template template = forConfigDrive.getInstance(TemplateBuilder.class).build(); + template.getOptions().as(NovaTemplateOptions.class).configDrive(true); + + NovaComputeServiceAdapter adapter = forConfigDrive.getInstance(NovaComputeServiceAdapter.class); + + NodeAndInitialCredentials<ServerInZone> server = adapter.createNodeWithGroupEncodedIntoName("test", "test-e92", template); + assertNotNull(server); + } + public void testCreateNodeWithGroupEncodedIntoNameWhenSecurityGroupsArePresent() throws Exception { HttpRequest createServer = HttpRequest http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38cbd58/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptionsTest.java ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptionsTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptionsTest.java index 106da5b..22ee390 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptionsTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptionsTest.java @@ -203,7 +203,7 @@ public class NovaTemplateOptionsTest { options.diskConfig(Server.DISK_CONFIG_AUTO); assertEquals(options.getDiskConfig(), Server.DISK_CONFIG_AUTO); } - + @Test(expectedExceptions = IllegalArgumentException.class) public void testblockOnPortBadFormat() { NovaTemplateOptions options = new NovaTemplateOptions(); http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38cbd58/apis/openstack-nova/src/test/resources/new_server_config_drive.json ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/test/resources/new_server_config_drive.json b/apis/openstack-nova/src/test/resources/new_server_config_drive.json new file mode 100644 index 0000000..7a94bea --- /dev/null +++ b/apis/openstack-nova/src/test/resources/new_server_config_drive.json @@ -0,0 +1,42 @@ +{ + "server": { + "status": "BUILD(scheduling)", + "updated": "2012-03-19T06:21:13Z", + "hostId": "", + "user_id": "54297837463082", + "name": "test-e92", + "links": [{ + "href": "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/37936628937291/servers/71752", + "rel": "self" + }, { + "href": "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/37936628937291/servers/71752", + "rel": "bookmark" + }], + "addresses": {}, + "tenant_id": "37936628937291", + "image": { + "id": "1241", + "links": [{ + "href": "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/37936628937291/images/1241", + "rel": "bookmark" + }] + }, + "created": "2012-03-19T06:21:13Z", + "uuid": "47491020-6a78-4f63-9475-23195ac4515c", + "accessIPv4": "", + "accessIPv6": "", + "key_name": null, + "adminPass": "ZWuHcmTMQ7eXoHeM", + "flavor": { + "id": "100", + "links": [{ + "href": "https://az-1.region-a.geo-1.compute.hpcloudsvc.com/37936628937291/flavors/100", + "rel": "bookmark" + }] + }, + "config_drive": "true", + "id": 71752, + "metadata": {}, + "OS-DCF:diskConfig": "AUTO" + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38cbd58/apis/openstack-nova/src/test/resources/server_details.json ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/test/resources/server_details.json b/apis/openstack-nova/src/test/resources/server_details.json index f548785..b5936c5 100644 --- a/apis/openstack-nova/src/test/resources/server_details.json +++ b/apis/openstack-nova/src/test/resources/server_details.json @@ -11,7 +11,7 @@ "accessIPv6" : "::babe:67.23.10.132", "status": "BUILD(scheduling)", "progress": 60, - "OS-DCF:diskConfig": "AUTO", + "OS-DCF:diskConfig": "AUTO", "image" : { "id": "52415800-8b69-11e0-9b19-734f6f006e54", "links": [
