openstack-nova: add support for user-data

This commit is contained in:
Mathieu Guillaume 2012-05-08 11:27:41 +02:00 committed by Adrian Cole
parent a45d079b8c
commit ab22b0606b
4 changed files with 58 additions and 5 deletions

View File

@ -104,6 +104,7 @@ public class NovaComputeServiceAdapter implements
CreateServerOptions options = new CreateServerOptions(); CreateServerOptions options = new CreateServerOptions();
options.metadata(templateOptions.getUserMetadata()); options.metadata(templateOptions.getUserMetadata());
options.securityGroupNames(templateOptions.getSecurityGroupNames()); options.securityGroupNames(templateOptions.getSecurityGroupNames());
options.userData(templateOptions.getUserData());
Optional<String> privateKey = Optional.absent(); Optional<String> privateKey = Optional.absent();
if (templateOptions.getKeyPairName() != null) { if (templateOptions.getKeyPairName() != null) {

View File

@ -19,8 +19,10 @@
package org.jclouds.openstack.nova.v1_1.compute.options; package org.jclouds.openstack.nova.v1_1.compute.options;
import static com.google.common.base.Objects.equal; import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -68,6 +70,9 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
eTo.securityGroupNames(getSecurityGroupNames()); eTo.securityGroupNames(getSecurityGroupNames());
eTo.generateKeyPair(shouldGenerateKeyPair()); eTo.generateKeyPair(shouldGenerateKeyPair());
eTo.keyPairName(getKeyPairName()); eTo.keyPairName(getKeyPairName());
if (getUserData() != null) {
eTo.userData(getUserData());
}
} }
} }
@ -75,6 +80,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
protected Set<String> securityGroupNames = ImmutableSet.of(); protected Set<String> securityGroupNames = ImmutableSet.of();
protected boolean generateKeyPair = false; protected boolean generateKeyPair = false;
protected String keyPairName; protected String keyPairName;
protected byte[] userData;
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
@ -85,19 +91,21 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
NovaTemplateOptions that = NovaTemplateOptions.class.cast(o); NovaTemplateOptions that = NovaTemplateOptions.class.cast(o);
return super.equals(that) && equal(this.autoAssignFloatingIp, that.autoAssignFloatingIp) return super.equals(that) && equal(this.autoAssignFloatingIp, that.autoAssignFloatingIp)
&& equal(this.securityGroupNames, that.securityGroupNames) && equal(this.securityGroupNames, that.securityGroupNames)
&& equal(this.generateKeyPair, that.generateKeyPair) && equal(this.keyPairName, that.keyPairName); && equal(this.generateKeyPair, that.generateKeyPair)
&& equal(this.keyPairName, that.keyPairName)
&& Arrays.equals(this.userData, that.userData);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, securityGroupNames, generateKeyPair, keyPairName); return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, securityGroupNames, generateKeyPair, keyPairName, userData);
} }
@Override @Override
public ToStringHelper string() { public ToStringHelper string() {
return super.string().add("autoAssignFloatingIp", autoAssignFloatingIp) return super.string().add("autoAssignFloatingIp", autoAssignFloatingIp)
.add("securityGroupNames", securityGroupNames).add("generateKeyPair", generateKeyPair) .add("securityGroupNames", securityGroupNames).add("generateKeyPair", generateKeyPair)
.add("keyPairName", keyPairName); .add("keyPairName", keyPairName).add("UserData", userData);
} }
public static final NovaTemplateOptions NONE = new NovaTemplateOptions(); public static final NovaTemplateOptions NONE = new NovaTemplateOptions();
@ -183,6 +191,10 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
return securityGroupNames; return securityGroupNames;
} }
public byte[] getUserData() {
return userData;
}
public static class Builder { public static class Builder {
/** /**
@ -312,6 +324,14 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
return options.blockUntilRunning(blockUntilRunning); return options.blockUntilRunning(blockUntilRunning);
} }
/**
* @see NovaTemplateOptions#userData
*/
public static NovaTemplateOptions userData(byte[] userData) {
NovaTemplateOptions options = new NovaTemplateOptions();
return NovaTemplateOptions.class.cast(options.userData(userData));
}
} }
// methods that only facilitate returning the correct object type // methods that only facilitate returning the correct object type
@ -444,4 +464,15 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
return NovaTemplateOptions.class.cast(super.userMetadata(key, value)); return NovaTemplateOptions.class.cast(super.userMetadata(key, value));
} }
/**
* 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;
}
} }

View File

@ -110,6 +110,7 @@ public class CreateServerOptions implements MapBinder {
private Set<String> securityGroupNames = ImmutableSet.of(); private Set<String> securityGroupNames = ImmutableSet.of();
private Map<String, String> metadata = ImmutableMap.of(); private Map<String, String> metadata = ImmutableMap.of();
private List<File> personality = Lists.newArrayList(); private List<File> personality = Lists.newArrayList();
private byte[] userData;
@Override @Override
public boolean equals(Object object) { public boolean equals(Object object) {
@ -132,8 +133,9 @@ public class CreateServerOptions implements MapBinder {
} }
protected ToStringHelper string() { protected ToStringHelper string() {
return toStringHelper("").add("keyName", "keyName").add("securityGroupNames", securityGroupNames).add("metadata", return toStringHelper("").add("keyName", "keyName").add("securityGroupNames", securityGroupNames)
metadata).add("personality", personality).add("adminPassPresent", adminPass != null); .add("metadata", metadata).add("personality", personality)
.add("adminPassPresent", adminPass != null).add("userData", new String(userData));
} }
@Override @Override
@ -152,6 +154,7 @@ public class CreateServerOptions implements MapBinder {
String key_name; String key_name;
@SerializedName(value = "security_groups") @SerializedName(value = "security_groups")
Set<SecurityGroup> securityGroupNames; Set<SecurityGroup> securityGroupNames;
String user_data;
private ServerRequest(String name, String imageRef, String flavorRef) { private ServerRequest(String name, String imageRef, String flavorRef) {
this.name = name; this.name = name;
@ -172,6 +175,8 @@ public class CreateServerOptions implements MapBinder {
server.personality = personality; server.personality = personality;
if (keyName != null) if (keyName != null)
server.key_name = keyName; server.key_name = keyName;
if (userData != null)
server.user_data = Base64.encodeBytes(userData);
if (securityGroupNames.size() > 0) { if (securityGroupNames.size() > 0) {
server.securityGroupNames = Sets.newHashSet(); server.securityGroupNames = Sets.newHashSet();
for (String groupName : securityGroupNames) { for (String groupName : securityGroupNames) {
@ -240,6 +245,16 @@ public class CreateServerOptions implements MapBinder {
return this; return this;
} }
/**
* 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.
*/
public CreateServerOptions userData(byte[] userData) {
this.userData = userData;
return this;
}
/** /**
* A keypair name can be defined when creating a server. This key will be * 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 * linked to the server and used to SSH connect to the machine

View File

@ -190,6 +190,12 @@ public class NovaTemplateOptionsTest {
authorizePublicKey(null); authorizePublicKey(null);
} }
@Test
public void testUserData() {
NovaTemplateOptions options = new NovaTemplateOptions();
options.userData("test".getBytes());
assertEquals(new String(options.getUserData()), "test");
}
@Test(expectedExceptions = IllegalArgumentException.class) @Test(expectedExceptions = IllegalArgumentException.class)
public void testblockOnPortBadFormat() { public void testblockOnPortBadFormat() {
NovaTemplateOptions options = new NovaTemplateOptions(); NovaTemplateOptions options = new NovaTemplateOptions();