mirror of https://github.com/apache/jclouds.git
Support Disk Configuration Extension
This commit is contained in:
parent
675c649cb6
commit
e6b6e4edb2
|
@ -25,6 +25,7 @@ import java.util.Map;
|
|||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
|
||||
import org.jclouds.openstack.v2_0.domain.Link;
|
||||
import org.jclouds.openstack.v2_0.domain.Resource;
|
||||
|
||||
|
@ -45,6 +46,8 @@ import com.google.common.collect.Multimap;
|
|||
* />
|
||||
*/
|
||||
public class Server extends Resource {
|
||||
public final static String DISK_CONFIG_MANUAL = "MANUAL";
|
||||
public final static String DISK_CONFIG_AUTO = "AUTO";
|
||||
|
||||
/**
|
||||
* Servers contain a status attribute that can be used as an indication of the current server
|
||||
|
@ -441,12 +444,18 @@ public class Server extends Resource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Disk config attribute from the Disk Config Extension (alias "OS-DCF")
|
||||
* Disk config attribute from the Disk Config Extension (alias "OS-DCF").
|
||||
* One of {@link Server#DISK_CONFIG_AUTO} or {@link Server#DISK_CONFIG_MANUAL}.
|
||||
* This field is only present if the Disk Config extension is installed.
|
||||
* <p/>
|
||||
* NOTE: This field is only present if the Disk Config extension is installed
|
||||
* NOTE: Typically a field like this would be implemented as an enum but this field was
|
||||
* originally implmented as a String and {@link Server#DISK_CONFIG_AUTO} and
|
||||
* {@link Server#DISK_CONFIG_MANUAL} were added later as Strings to preserve backwards
|
||||
* compatibility.
|
||||
*
|
||||
* @see org.jclouds.openstack.nova.v2_0.features.ExtensionApi#getExtensionByAlias
|
||||
* @see org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces#DISK_CONFIG
|
||||
* @see CreateServerOptions#getDiskConfig()
|
||||
*/
|
||||
public Optional<String> getDiskConfig() {
|
||||
return this.diskConfig;
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.beans.ConstructorProperties;
|
|||
import java.util.Set;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
|
||||
import org.jclouds.openstack.v2_0.domain.Link;
|
||||
import org.jclouds.openstack.v2_0.domain.Resource;
|
||||
|
||||
|
@ -47,6 +48,7 @@ public class ServerCreated extends Resource {
|
|||
|
||||
public static final class Builder extends Resource.Builder<Builder> {
|
||||
protected String adminPass;
|
||||
protected String diskConfig;
|
||||
|
||||
/**
|
||||
* @see ServerCreated#getAdminPass()
|
||||
|
@ -55,13 +57,21 @@ public class ServerCreated extends Resource {
|
|||
this.adminPass = adminPass;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ServerCreated#getDiskConfig()
|
||||
*/
|
||||
public Builder diskConfig(String diskConfig) {
|
||||
this.diskConfig = diskConfig;
|
||||
return self();
|
||||
}
|
||||
|
||||
public ServerCreated build() {
|
||||
return new ServerCreated(id, name, links, adminPass);
|
||||
return new ServerCreated(id, name, links, adminPass, diskConfig);
|
||||
}
|
||||
|
||||
public Builder fromServerCreated(ServerCreated in) {
|
||||
return super.fromResource(in).adminPass(in.getAdminPass().orNull());
|
||||
return super.fromResource(in).adminPass(in.getAdminPass().orNull()).diskConfig(in.getDiskConfig().orNull());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,13 +81,16 @@ public class ServerCreated extends Resource {
|
|||
}
|
||||
|
||||
private final Optional<String> adminPass;
|
||||
private final Optional<String> diskConfig;
|
||||
|
||||
@ConstructorProperties({
|
||||
"id", "name", "links", "adminPass"
|
||||
"id", "name", "links", "adminPass", "OS-DCF:diskConfig"
|
||||
})
|
||||
protected ServerCreated(String id, @Nullable String name, Set<Link> links, @Nullable String adminPass) {
|
||||
protected ServerCreated(String id, @Nullable String name, Set<Link> links, @Nullable String adminPass,
|
||||
@Nullable String diskConfig) {
|
||||
super(id, name, links);
|
||||
this.adminPass = Optional.fromNullable(adminPass);
|
||||
this.diskConfig = Optional.fromNullable(diskConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,9 +100,16 @@ public class ServerCreated extends Resource {
|
|||
return this.adminPass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#getDiskConfig()
|
||||
*/
|
||||
public Optional<String> getDiskConfig() {
|
||||
return this.diskConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(adminPass);
|
||||
return Objects.hashCode(adminPass, diskConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -97,11 +117,12 @@ public class ServerCreated extends Resource {
|
|||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
ServerCreated that = ServerCreated.class.cast(obj);
|
||||
return super.equals(that) && Objects.equal(this.adminPass, that.adminPass);
|
||||
return super.equals(that) && Objects.equal(this.adminPass, that.adminPass)
|
||||
&& Objects.equal(this.diskConfig, that.diskConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ToStringHelper string() {
|
||||
return super.string().add("adminPass", adminPass.orNull());
|
||||
return super.string().add("adminPass", adminPass.orNull()).add("diskConfig", diskConfig.orNull());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import javax.inject.Named;
|
|||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.openstack.nova.v2_0.NovaApi;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
||||
import org.jclouds.rest.MapBinder;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
|
||||
|
@ -109,6 +110,7 @@ public class CreateServerOptions implements MapBinder {
|
|||
private Map<String, String> metadata = ImmutableMap.of();
|
||||
private List<File> personality = Lists.newArrayList();
|
||||
private byte[] userData;
|
||||
private String diskConfig;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
|
@ -119,7 +121,7 @@ public class CreateServerOptions implements MapBinder {
|
|||
final CreateServerOptions other = CreateServerOptions.class.cast(object);
|
||||
return equal(keyName, other.keyName) && equal(securityGroupNames, other.securityGroupNames)
|
||||
&& equal(metadata, other.metadata) && equal(personality, other.personality)
|
||||
&& equal(adminPass, other.adminPass);
|
||||
&& equal(adminPass, other.adminPass) && equal(diskConfig, other.diskConfig);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -141,6 +143,8 @@ public class CreateServerOptions implements MapBinder {
|
|||
toString.add("personality", personality);
|
||||
if (adminPass != null)
|
||||
toString.add("adminPassPresent", true);
|
||||
if (diskConfig != null)
|
||||
toString.add("diskConfig", diskConfig);
|
||||
toString.add("userData", userData == null ? null : new String(userData));
|
||||
return toString;
|
||||
}
|
||||
|
@ -161,6 +165,8 @@ public class CreateServerOptions implements MapBinder {
|
|||
@Named("security_groups")
|
||||
Set<NamedThingy> securityGroupNames;
|
||||
String user_data;
|
||||
@Named("OS-DCF:diskConfig")
|
||||
String diskConfig;
|
||||
|
||||
private ServerRequest(String name, String imageRef, String flavorRef) {
|
||||
this.name = name;
|
||||
|
@ -192,6 +198,9 @@ public class CreateServerOptions implements MapBinder {
|
|||
if (adminPass != null) {
|
||||
server.adminPass = adminPass;
|
||||
}
|
||||
if (diskConfig != null) {
|
||||
server.diskConfig = diskConfig;
|
||||
}
|
||||
|
||||
return bindToRequest(request, ImmutableMap.of("server", server));
|
||||
}
|
||||
|
@ -320,6 +329,29 @@ public class CreateServerOptions implements MapBinder {
|
|||
this.securityGroupNames = ImmutableSet.copyOf(securityGroupNames);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When you create a server from an image with the diskConfig value set to
|
||||
* {@link Server#DISK_CONFIG_AUTO}, the server is built with a single partition that is expanded to
|
||||
* the disk size of the flavor selected. When you set the diskConfig attribute to
|
||||
* {@link Server#DISK_CONFIG_MANUAL}, the server is built by using the partition scheme and file
|
||||
* system that is in the source image.
|
||||
* <p/>
|
||||
* If the target flavor disk is larger, remaining disk space is left unpartitioned. A server inherits the diskConfig
|
||||
* attribute from the image from which it is created. However, you can override the diskConfig value when you create
|
||||
* a server. This field is only present if the Disk Config extension is installed in your OpenStack deployment.
|
||||
*/
|
||||
public String getDiskConfig() {
|
||||
return diskConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getDiskConfig
|
||||
*/
|
||||
public CreateServerOptions diskConfig(String diskConfig) {
|
||||
this.diskConfig = diskConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
|
@ -367,6 +399,14 @@ public class CreateServerOptions implements MapBinder {
|
|||
CreateServerOptions options = new CreateServerOptions();
|
||||
return CreateServerOptions.class.cast(options.securityGroupNames(groupNames));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#getDiskConfig
|
||||
*/
|
||||
public static CreateServerOptions diskConfig(String diskConfig) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return CreateServerOptions.class.cast(options.diskConfig(diskConfig));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,6 +23,7 @@ import static org.testng.Assert.fail;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.openstack.nova.v2_0.NovaApi;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
||||
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiExpectTest;
|
||||
import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
|
||||
import org.jclouds.openstack.nova.v2_0.parse.ParseCreatedServerTest;
|
||||
|
@ -127,6 +128,58 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
|
|||
new ParseCreatedServerTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testCreateServerWithDiskConfigAuto() 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\",\"OS-DCF:diskConfig\":\"AUTO\"}}","application/json"))
|
||||
.build();
|
||||
|
||||
|
||||
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
|
||||
.payload(payloadFromResourceWithContentType("/new_server_disk_config_auto.json","application/json; charset=UTF-8")).build();
|
||||
|
||||
|
||||
NovaApi apiWithNewServer = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess,
|
||||
createServer, createServerResponse);
|
||||
|
||||
assertEquals(apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").create("test-e92", "1241",
|
||||
"100", new CreateServerOptions().diskConfig(Server.DISK_CONFIG_AUTO)).toString(),
|
||||
new ParseCreatedServerTest().expectedWithDiskConfig(Server.DISK_CONFIG_AUTO).toString());
|
||||
}
|
||||
|
||||
public void testCreateServerWithDiskConfigManual() 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\",\"OS-DCF:diskConfig\":\"MANUAL\"}}","application/json"))
|
||||
.build();
|
||||
|
||||
|
||||
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
|
||||
.payload(payloadFromResourceWithContentType("/new_server_disk_config_manual.json","application/json; charset=UTF-8")).build();
|
||||
|
||||
|
||||
NovaApi apiWithNewServer = requestsSendResponses(
|
||||
keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess,
|
||||
createServer, createServerResponse);
|
||||
|
||||
assertEquals(apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").create("test-e92", "1241",
|
||||
"100", new CreateServerOptions().diskConfig(Server.DISK_CONFIG_MANUAL)).toString(),
|
||||
new ParseCreatedServerTest().expectedWithDiskConfig(Server.DISK_CONFIG_MANUAL).toString());
|
||||
}
|
||||
|
||||
public void testCreateImageWhenResponseIs2xx() throws Exception {
|
||||
String serverId = "123";
|
||||
String imageId = "456";
|
||||
|
|
|
@ -59,6 +59,21 @@ public class ParseCreatedServerTest extends BaseItemParserTest<ServerCreated> {
|
|||
|
||||
}
|
||||
|
||||
@SelectJson("server")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public ServerCreated expectedWithDiskConfig(String diskConfig) {
|
||||
return ServerCreated
|
||||
.builder()
|
||||
.id("71752")
|
||||
.name("test-e92")
|
||||
.adminPass("ZWuHcmTMQ7eXoHeM")
|
||||
.diskConfig(diskConfig)
|
||||
.links(
|
||||
Link.create(Relation.SELF, URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/37936628937291/servers/71752")),
|
||||
Link.create(Relation.BOOKMARK, URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/37936628937291/servers/71752"))).build();
|
||||
|
||||
}
|
||||
|
||||
protected Injector injector() {
|
||||
return Guice.createInjector(new NovaParserModule(), new GsonModule());
|
||||
}
|
||||
|
|
|
@ -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": "",
|
||||
"id": 71752,
|
||||
"metadata": {},
|
||||
"OS-DCF:diskConfig": "AUTO"
|
||||
}
|
||||
}
|
|
@ -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": "",
|
||||
"id": 71752,
|
||||
"metadata": {},
|
||||
"OS-DCF:diskConfig": "MANUAL"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue