mirror of https://github.com/apache/jclouds.git
JCLOUDS-281: Support Nova Block Device Mapping v2 Boot
This commit is contained in:
parent
4c0f7e766d
commit
8122f0b38d
|
@ -16,76 +16,70 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import java.beans.ConstructorProperties;
|
||||
|
||||
import javax.inject.Named;
|
||||
import java.beans.ConstructorProperties;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
||||
|
||||
/**
|
||||
* A representation of a block device that should be attached to the Nova instance to be launched
|
||||
*
|
||||
* A representation of a block device that can be used to boot a Nova instance.
|
||||
*/
|
||||
public class BlockDeviceMapping {
|
||||
|
||||
@Named("delete_on_termination")
|
||||
String deleteOnTermination = "0";
|
||||
@Named("device_name")
|
||||
String deviceName = null;
|
||||
@Named("volume_id")
|
||||
String volumeId = null;
|
||||
@Named("volume_size")
|
||||
String volumeSize = "";
|
||||
private String uuid;
|
||||
@Named("device_name")
|
||||
private String deviceName;
|
||||
@Named("device_type")
|
||||
private String deviceType;
|
||||
@Named("volume_size")
|
||||
private Integer volumeSize;
|
||||
@Named("source_type")
|
||||
private String sourceType;
|
||||
@Named("destination_type")
|
||||
private String destinationType;
|
||||
@Named("disk_bus")
|
||||
private String diskBus;
|
||||
@Named("no_device")
|
||||
private Boolean noDevice;
|
||||
@Named("guest_format")
|
||||
private String guestFormat;
|
||||
@Named("boot_index")
|
||||
private Integer bootIndex;
|
||||
@Named("delete_on_termination")
|
||||
private Boolean deleteOnTermination;
|
||||
|
||||
@ConstructorProperties({"volume_id", "volume_size", "device_name", "delete_on_termination"})
|
||||
private BlockDeviceMapping(String volumeId, String volumeSize, String deviceName, String deleteOnTermination) {
|
||||
checkNotNull(volumeId);
|
||||
checkNotNull(deviceName);
|
||||
this.volumeId = volumeId;
|
||||
this.volumeSize = volumeSize;
|
||||
@ConstructorProperties({"uuid", "device_name", "device_type", "volume_size", "source_type", "destination_type",
|
||||
"disk_bus", "no_device", "guest_format", "boot_index", "delete_on_termination"})
|
||||
protected BlockDeviceMapping(String uuid, String deviceName, String deviceType, Integer volumeSize,
|
||||
String sourceType, String destinationType, String diskBus, Boolean noDevice, String guestFormat,
|
||||
Integer bootIndex, Boolean deleteOnTermination) {
|
||||
this.uuid = uuid;
|
||||
this.deviceName = deviceName;
|
||||
if (deleteOnTermination != null) {
|
||||
this.deleteOnTermination = deleteOnTermination;
|
||||
}
|
||||
this.deviceType = deviceType;
|
||||
this.volumeSize = volumeSize;
|
||||
this.sourceType = sourceType;
|
||||
this.destinationType = destinationType;
|
||||
this.diskBus = diskBus;
|
||||
this.noDevice = noDevice;
|
||||
this.guestFormat = guestFormat;
|
||||
this.bootIndex = bootIndex;
|
||||
this.deleteOnTermination = deleteOnTermination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
private BlockDeviceMapping() {}
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
* @param blockDeviceMapping
|
||||
*/
|
||||
private BlockDeviceMapping(BlockDeviceMapping blockDeviceMapping) {
|
||||
this(blockDeviceMapping.volumeId,
|
||||
blockDeviceMapping.volumeSize,
|
||||
blockDeviceMapping.deviceName,
|
||||
blockDeviceMapping.deleteOnTermination);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the volume id of the block device
|
||||
* @return the uuid of the volume
|
||||
*/
|
||||
@Nullable
|
||||
public String getVolumeId() {
|
||||
return volumeId;
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the size of the block device
|
||||
*/
|
||||
@Nullable
|
||||
public String getVolumeSize() {
|
||||
return volumeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the device name to which the volume is attached
|
||||
* @return the device name
|
||||
*/
|
||||
@Nullable
|
||||
public String getDeviceName() {
|
||||
|
@ -93,15 +87,81 @@ public class BlockDeviceMapping {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return whether the volume should be deleted on terminating the instance
|
||||
* @return the device type
|
||||
*/
|
||||
public String getDeleteOnTermination() {
|
||||
return deviceName;
|
||||
@Nullable
|
||||
public String getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the size of the volume
|
||||
*/
|
||||
@Nullable
|
||||
public Integer getVolumeSize() {
|
||||
return volumeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the source type of the block device
|
||||
*/
|
||||
@Nullable
|
||||
public String getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the destination type of the block device
|
||||
*/
|
||||
@Nullable
|
||||
public String getDestinationType() {
|
||||
return destinationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the disk bus of the block device
|
||||
*/
|
||||
@Nullable
|
||||
public String getDiskBus() {
|
||||
return diskBus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if there is no block device
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean getNoDevice() {
|
||||
return noDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the guest format of the block device
|
||||
*/
|
||||
@Nullable
|
||||
public String getGuestFormat() {
|
||||
return guestFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the boot index of the block device
|
||||
*/
|
||||
@Nullable
|
||||
public Integer getBootIndex() {
|
||||
return bootIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the block device should terminate on deletion
|
||||
*/
|
||||
@Nullable
|
||||
public Boolean getDeleteOnTermination() {
|
||||
return deleteOnTermination;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(volumeId, volumeSize, deviceName, deleteOnTermination);
|
||||
return Objects.hashCode(uuid, deviceName, deviceType, volumeSize, sourceType, destinationType, diskBus,
|
||||
noDevice, guestFormat, bootIndex, deleteOnTermination);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -111,168 +171,134 @@ public class BlockDeviceMapping {
|
|||
if (obj == null || getClass() != obj.getClass())
|
||||
return false;
|
||||
BlockDeviceMapping that = BlockDeviceMapping.class.cast(obj);
|
||||
return Objects.equal(this.volumeId, that.volumeId)
|
||||
&& Objects.equal(this.volumeSize, that.volumeSize)
|
||||
return Objects.equal(this.uuid, that.uuid)
|
||||
&& Objects.equal(this.deviceName, that.deviceName)
|
||||
&& Objects.equal(this.deviceType, that.deviceType)
|
||||
&& Objects.equal(this.volumeSize, that.volumeSize)
|
||||
&& Objects.equal(this.sourceType, that.sourceType)
|
||||
&& Objects.equal(this.destinationType, that.destinationType)
|
||||
&& Objects.equal(this.diskBus, that.diskBus)
|
||||
&& Objects.equal(this.noDevice, that.noDevice)
|
||||
&& Objects.equal(this.guestFormat, that.guestFormat)
|
||||
&& Objects.equal(this.bootIndex, that.bootIndex)
|
||||
&& Objects.equal(this.deleteOnTermination, that.deleteOnTermination);
|
||||
}
|
||||
|
||||
protected ToStringHelper string() {
|
||||
return Objects.toStringHelper(this)
|
||||
.add("uuid", uuid)
|
||||
.add("deviceName", deviceName)
|
||||
.add("deviceType", deviceType)
|
||||
.add("volumeSize", volumeSize)
|
||||
.add("sourceType", sourceType)
|
||||
.add("destinationType", destinationType)
|
||||
.add("diskBus", diskBus)
|
||||
.add("noDevice", noDevice)
|
||||
.add("guestFormat", guestFormat)
|
||||
.add("bootIndex", bootIndex)
|
||||
.add("deleteOnTermination", deleteOnTermination);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toStringHelper(this)
|
||||
.add("volumeId", volumeId)
|
||||
.add("volumeSize", volumeSize)
|
||||
.add("deviceName", deviceName)
|
||||
.add("deleteOnTermination", deleteOnTermination)
|
||||
.toString();
|
||||
return string().toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Methods to get the Create and Update builders follow
|
||||
*/
|
||||
|
||||
/**
|
||||
* @return the Builder for creating a new block device mapping
|
||||
*/
|
||||
public static CreateBuilder createOptions(String volumeId, String deviceName) {
|
||||
return new CreateBuilder(volumeId, deviceName);
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the Builder for updating a block device mapping
|
||||
*/
|
||||
public static UpdateBuilder updateOptions() {
|
||||
return new UpdateBuilder();
|
||||
public Builder toBuilder() {
|
||||
return builder().fromBlockDeviceMapping(this);
|
||||
}
|
||||
|
||||
private abstract static class Builder<ParameterizedBuilderType> {
|
||||
protected BlockDeviceMapping blockDeviceMapping;
|
||||
public static class Builder {
|
||||
protected String uuid;
|
||||
protected String deviceName;
|
||||
protected String deviceType;
|
||||
protected Integer volumeSize;
|
||||
protected String sourceType;
|
||||
protected String destinationType;
|
||||
protected String diskBus;
|
||||
protected Boolean noDevice;
|
||||
protected String guestFormat;
|
||||
protected Integer bootIndex;
|
||||
protected Boolean deleteOnTermination;
|
||||
|
||||
/**
|
||||
* No-parameters constructor used when updating.
|
||||
* */
|
||||
private Builder() {
|
||||
blockDeviceMapping = new BlockDeviceMapping();
|
||||
}
|
||||
|
||||
protected abstract ParameterizedBuilderType self();
|
||||
|
||||
/**
|
||||
* Provide the volume id to the BlockDeviceMapping's Builder.
|
||||
*
|
||||
* @return the Builder.
|
||||
* @see BlockDeviceMapping#getVolumeId()
|
||||
*/
|
||||
public ParameterizedBuilderType volumeId(String volumeId) {
|
||||
blockDeviceMapping.volumeId = volumeId;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the volume size in GB to the BlockDeviceMapping's Builder.
|
||||
*
|
||||
* @return the Builder.
|
||||
* @see BlockDeviceMapping#getVolumeSize()
|
||||
*/
|
||||
public ParameterizedBuilderType volumeSize(int volumeSize) {
|
||||
blockDeviceMapping.volumeSize = Integer.toString(volumeSize);
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the deviceName to the BlockDeviceMapping's Builder.
|
||||
*
|
||||
* @return the Builder.
|
||||
* @see BlockDeviceMapping#getDeviceName()
|
||||
*/
|
||||
public ParameterizedBuilderType deviceName(String deviceName) {
|
||||
blockDeviceMapping.deviceName = deviceName;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an option indicated to delete the volume on instance deletion to BlockDeviceMapping's Builder.
|
||||
*
|
||||
* @return the Builder.
|
||||
* @see BlockDeviceMapping#getVolumeSize()
|
||||
*/
|
||||
public ParameterizedBuilderType deleteOnTermination(boolean deleteOnTermination) {
|
||||
blockDeviceMapping.deleteOnTermination = deleteOnTermination ? "1" : "0";
|
||||
return self();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and Update builders (inheriting from Builder)
|
||||
*/
|
||||
public static class CreateBuilder extends Builder<CreateBuilder> {
|
||||
/**
|
||||
* Supply required properties for creating a Builder
|
||||
*/
|
||||
private CreateBuilder(String volumeId, String deviceName) {
|
||||
blockDeviceMapping.volumeId = volumeId;
|
||||
blockDeviceMapping.deviceName = deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a CreateOptions constructed with this Builder.
|
||||
*/
|
||||
public CreateOptions build() {
|
||||
return new CreateOptions(blockDeviceMapping);
|
||||
}
|
||||
|
||||
protected CreateBuilder self() {
|
||||
public Builder uuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and Update builders (inheriting from Builder)
|
||||
*/
|
||||
public static class UpdateBuilder extends Builder<UpdateBuilder> {
|
||||
/**
|
||||
* Supply required properties for updating a Builder
|
||||
*/
|
||||
private UpdateBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a UpdateOptions constructed with this Builder.
|
||||
*/
|
||||
public UpdateOptions build() {
|
||||
return new UpdateOptions(blockDeviceMapping);
|
||||
}
|
||||
|
||||
protected UpdateBuilder self() {
|
||||
public Builder deviceName(String deviceName) {
|
||||
this.deviceName = deviceName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and Update options - extend the domain class, passed to API update and create calls.
|
||||
* Essentially the same as the domain class. Ensure validation and safe typing.
|
||||
*/
|
||||
public static class CreateOptions extends BlockDeviceMapping {
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
private CreateOptions(BlockDeviceMapping blockDeviceMapping) {
|
||||
super(blockDeviceMapping);
|
||||
checkNotNull(blockDeviceMapping.volumeId, "volume id should not be null");
|
||||
checkNotNull(blockDeviceMapping.deviceName, "device name should not be null");
|
||||
public Builder deviceType(String deviceType) {
|
||||
this.deviceType = deviceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder volumeSize(Integer volumeSize) {
|
||||
this.volumeSize = volumeSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder sourceType(String sourceType) {
|
||||
this.sourceType = sourceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder destinationType(String destinationType) {
|
||||
this.destinationType = destinationType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder diskBus(String diskBus) {
|
||||
this.diskBus = diskBus;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder noDevice(Boolean noDevice) {
|
||||
this.noDevice = noDevice;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder guestFormat(String guestFormat) {
|
||||
this.guestFormat = guestFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder bootIndex(Integer bootIndex) {
|
||||
this.bootIndex = bootIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder deleteOnTermination(Boolean deleteOnTermination) {
|
||||
this.deleteOnTermination = deleteOnTermination;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BlockDeviceMapping build() {
|
||||
return new BlockDeviceMapping(uuid, deviceName, deviceType, volumeSize, sourceType, destinationType, diskBus,
|
||||
noDevice, guestFormat, bootIndex, deleteOnTermination);
|
||||
}
|
||||
|
||||
public Builder fromBlockDeviceMapping(BlockDeviceMapping in) {
|
||||
return this
|
||||
.uuid(in.getUuid())
|
||||
.deviceName(in.getDeviceName())
|
||||
.deviceType(in.getDeviceType())
|
||||
.volumeSize(in.getVolumeSize())
|
||||
.sourceType(in.getSourceType())
|
||||
.destinationType(in.getDestinationType())
|
||||
.diskBus(in.getDiskBus())
|
||||
.noDevice(in.getNoDevice())
|
||||
.bootIndex(in.getBootIndex())
|
||||
.deleteOnTermination(in.getDeleteOnTermination())
|
||||
.guestFormat(in.getGuestFormat());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and Update options - extend the domain class, passed to API update and create calls.
|
||||
* Essentially the same as the domain class. Ensure validation and safe typing.
|
||||
*/
|
||||
public static class UpdateOptions extends BlockDeviceMapping {
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
private UpdateOptions(BlockDeviceMapping blockDeviceMapping) {
|
||||
super(blockDeviceMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
package org.jclouds.openstack.nova.v2_0.extensions;
|
||||
|
||||
/**
|
||||
* Extension namespaces
|
||||
*
|
||||
* @see <a href= "http://nova.openstack.org/api_ext/" />
|
||||
* OpenStack Nova Extension Namespaces
|
||||
*/
|
||||
public interface ExtensionNamespaces {
|
||||
public final class ExtensionNamespaces {
|
||||
/**
|
||||
* Keypair Support
|
||||
*/
|
||||
|
@ -30,6 +28,10 @@ public interface ExtensionNamespaces {
|
|||
* Volumes support
|
||||
*/
|
||||
public static final String VOLUMES = "http://docs.openstack.org/ext/volumes/api/v1.1";
|
||||
/**
|
||||
* Volume attachment support
|
||||
*/
|
||||
public static final String VOLUME_ATTACHMENTS = "http://docs.openstack.org/compute/ext/os-volume-attachment-update/api/v2";
|
||||
/**
|
||||
* Volume types support
|
||||
*/
|
||||
|
@ -90,24 +92,29 @@ public interface ExtensionNamespaces {
|
|||
* Admin Action extension
|
||||
*/
|
||||
public static final String ADMIN_ACTIONS = "http://docs.openstack.org/ext/admin-actions/api/v1.1";
|
||||
|
||||
/**
|
||||
* Extended Server Status extension
|
||||
*/
|
||||
public static final String EXTENDED_STATUS = "http://docs.openstack.org/compute/ext/extended_status/api/v1.1";
|
||||
|
||||
/**
|
||||
* Disk Config extension
|
||||
*/
|
||||
public static final String DISK_CONFIG = "http://docs.openstack.org/compute/ext/disk_config/api/v1.1";
|
||||
|
||||
/**
|
||||
* Aggregates extension
|
||||
*/
|
||||
public static final String AGGREGATES = "http://docs.openstack.org/ext/aggregates/api/v1.1";
|
||||
|
||||
/**
|
||||
* Consoles extension
|
||||
*/
|
||||
public static final String CONSOLES = "http://docs.openstack.org/compute/ext/os-consoles/api/v2";
|
||||
/**
|
||||
* Block Device Mapping v2 Boot Extension
|
||||
*/
|
||||
public static final String BLOCK_DEVICE_MAPPING_V2_BOOT =
|
||||
"http://docs.openstack.org/compute/ext/block_device_mapping_v2_boot/api/v2";
|
||||
|
||||
private ExtensionNamespaces() {
|
||||
throw new AssertionError("intentionally unimplemented");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ public class CreateServerOptions implements MapBinder {
|
|||
private Set<Network> novaNetworks = ImmutableSet.of();
|
||||
private String availabilityZone;
|
||||
private boolean configDrive;
|
||||
private Set<BlockDeviceMapping> blockDeviceMapping = ImmutableSet.of();
|
||||
private Set<BlockDeviceMapping> blockDeviceMappings = ImmutableSet.of();
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
|
@ -118,12 +118,14 @@ public class CreateServerOptions implements MapBinder {
|
|||
}
|
||||
if (object instanceof CreateServerOptions) {
|
||||
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(diskConfig, other.diskConfig)
|
||||
&& equal(adminPass, other.adminPass) && equal(networks, other.networks)
|
||||
return equal(keyName, other.keyName) && equal(adminPass, other.adminPass)
|
||||
&& equal(securityGroupNames, other.securityGroupNames) && equal(metadata, other.metadata)
|
||||
&& equal(personality, other.personality)
|
||||
&& equal(diskConfig, other.diskConfig)
|
||||
&& equal(networks, other.networks)
|
||||
&& equal(availabilityZone, other.availabilityZone)
|
||||
&& equal(configDrive, other.configDrive);
|
||||
&& equal(configDrive, other.configDrive)
|
||||
&& equal(blockDeviceMappings, other.blockDeviceMappings);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -131,11 +133,12 @@ public class CreateServerOptions implements MapBinder {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(keyName, securityGroupNames, metadata, personality, adminPass, networks, availabilityZone, configDrive);
|
||||
return Objects.hashCode(keyName, adminPass, securityGroupNames, metadata, personality, networks, availabilityZone,
|
||||
configDrive, blockDeviceMappings);
|
||||
}
|
||||
|
||||
protected ToStringHelper string() {
|
||||
ToStringHelper toString = Objects.toStringHelper("").omitNullValues();
|
||||
ToStringHelper toString = Objects.toStringHelper(this);
|
||||
toString.add("keyName", keyName);
|
||||
if (securityGroupNames.size() > 0)
|
||||
toString.add("securityGroupNames", securityGroupNames);
|
||||
|
@ -150,10 +153,10 @@ public class CreateServerOptions implements MapBinder {
|
|||
toString.add("userData", userData == null ? null : new String(userData));
|
||||
if (!networks.isEmpty())
|
||||
toString.add("networks", networks);
|
||||
toString.add("availability_zone", availabilityZone == null ? null : availabilityZone);
|
||||
toString.add("availabilityZone", availabilityZone == null ? null : availabilityZone);
|
||||
toString.add("configDrive", configDrive);
|
||||
if (!blockDeviceMapping.isEmpty())
|
||||
toString.add("blockDeviceMapping", blockDeviceMapping);
|
||||
if (!blockDeviceMappings.isEmpty())
|
||||
toString.add("blockDeviceMappings", blockDeviceMappings);
|
||||
return toString;
|
||||
}
|
||||
|
||||
|
@ -180,8 +183,8 @@ public class CreateServerOptions implements MapBinder {
|
|||
Set<Map<String, String>> networks;
|
||||
@Named("config_drive")
|
||||
String configDrive;
|
||||
@Named("block_device_mapping")
|
||||
Set<BlockDeviceMapping> blockDeviceMapping;
|
||||
@Named("block_device_mapping_v2")
|
||||
Set<BlockDeviceMapping> blockDeviceMappings;
|
||||
|
||||
private ServerRequest(String name, String imageRef, String flavorRef) {
|
||||
this.name = name;
|
||||
|
@ -217,11 +220,9 @@ public class CreateServerOptions implements MapBinder {
|
|||
if (adminPass != null) {
|
||||
server.adminPass = adminPass;
|
||||
}
|
||||
|
||||
if (diskConfig != null) {
|
||||
server.diskConfig = diskConfig;
|
||||
}
|
||||
|
||||
if (!networks.isEmpty() || !novaNetworks.isEmpty()) {
|
||||
server.networks = Sets.newLinkedHashSet(); // ensures ordering is preserved - helps testing and more intuitive for users.
|
||||
for (Network network : novaNetworks) {
|
||||
|
@ -242,9 +243,8 @@ public class CreateServerOptions implements MapBinder {
|
|||
server.networks.add(ImmutableMap.of("uuid", network));
|
||||
}
|
||||
}
|
||||
|
||||
if (!blockDeviceMapping.isEmpty()) {
|
||||
server.blockDeviceMapping = blockDeviceMapping;
|
||||
if (!blockDeviceMappings.isEmpty()) {
|
||||
server.blockDeviceMappings = blockDeviceMappings;
|
||||
}
|
||||
|
||||
return bindToRequest(request, ImmutableMap.of("server", server));
|
||||
|
@ -318,7 +318,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.
|
||||
* Pass userData unencoded, as the value will be base64 encoded automatically.
|
||||
*/
|
||||
public CreateServerOptions userData(byte[] userData) {
|
||||
this.userData = userData;
|
||||
|
@ -339,21 +339,6 @@ public class CreateServerOptions implements MapBinder {
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
public String getKeyPairName() {
|
||||
return keyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The availability zone in which to launch the server.
|
||||
*
|
||||
* @return the availability zone to be used
|
||||
*/
|
||||
public String getAvailabilityZone() {
|
||||
return availabilityZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getKeyPairName()
|
||||
*/
|
||||
public CreateServerOptions keyPairName(String keyName) {
|
||||
|
@ -369,6 +354,75 @@ public class CreateServerOptions implements MapBinder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getSecurityGroupNames()
|
||||
*/
|
||||
public CreateServerOptions securityGroupNames(String... securityGroupNames) {
|
||||
return securityGroupNames(ImmutableSet.copyOf(checkNotNull(securityGroupNames, "securityGroupNames")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getSecurityGroupNames()
|
||||
*/
|
||||
public CreateServerOptions securityGroupNames(Iterable<String> securityGroupNames) {
|
||||
for (String groupName : checkNotNull(securityGroupNames, "securityGroupNames"))
|
||||
checkNotNull(emptyToNull(groupName), "all security groups must be non-empty");
|
||||
this.securityGroupNames = ImmutableSet.copyOf(securityGroupNames);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getDiskConfig()
|
||||
*/
|
||||
public CreateServerOptions diskConfig(String diskConfig) {
|
||||
this.diskConfig = diskConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getNetworks()
|
||||
*/
|
||||
public CreateServerOptions networks(Iterable<String> networks) {
|
||||
this.networks = ImmutableSet.copyOf(networks);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getNetworks()
|
||||
* Overwrites networks supplied by {@link #networks(Iterable)}
|
||||
*/
|
||||
public CreateServerOptions novaNetworks(Iterable<Network> networks) {
|
||||
this.novaNetworks = ImmutableSet.copyOf(networks);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getNetworks()
|
||||
*/
|
||||
public CreateServerOptions networks(String... networks) {
|
||||
return networks(ImmutableSet.copyOf(networks));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getBlockDeviceMappings()
|
||||
*/
|
||||
public CreateServerOptions blockDeviceMappings(Set<BlockDeviceMapping> blockDeviceMappings) {
|
||||
this.blockDeviceMappings = ImmutableSet.copyOf(blockDeviceMappings);
|
||||
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
|
||||
*/
|
||||
public String getKeyPairName() {
|
||||
return keyName;
|
||||
}
|
||||
|
||||
public String getAvailabilityZone() {
|
||||
return availabilityZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security groups the user specified to run servers with.
|
||||
* <p/>
|
||||
|
@ -401,23 +455,6 @@ public class CreateServerOptions implements MapBinder {
|
|||
return novaNetworks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getSecurityGroupNames
|
||||
*/
|
||||
public CreateServerOptions securityGroupNames(String... securityGroupNames) {
|
||||
return securityGroupNames(ImmutableSet.copyOf(checkNotNull(securityGroupNames, "securityGroupNames")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getSecurityGroupNames
|
||||
*/
|
||||
public CreateServerOptions securityGroupNames(Iterable<String> securityGroupNames) {
|
||||
for (String groupName : checkNotNull(securityGroupNames, "securityGroupNames"))
|
||||
checkNotNull(emptyToNull(groupName), "all security groups must be non-empty");
|
||||
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
|
||||
|
@ -433,14 +470,6 @@ public class CreateServerOptions implements MapBinder {
|
|||
return diskConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getDiskConfig
|
||||
*/
|
||||
public CreateServerOptions diskConfig(String diskConfig) {
|
||||
this.diskConfig = diskConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a configuration drive will be attached to the server or not.
|
||||
* This can be used for cloud-init or other configuration purposes.
|
||||
|
@ -450,56 +479,24 @@ public class CreateServerOptions implements MapBinder {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see #getNetworks
|
||||
* Block devices that should be attached to the instance at boot time.
|
||||
*/
|
||||
public CreateServerOptions networks(Iterable<String> networks) {
|
||||
this.networks = ImmutableSet.copyOf(networks);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getNetworks
|
||||
* Overwrites networks supplied by {@link #networks(Iterable)}
|
||||
*/
|
||||
public CreateServerOptions novaNetworks(Iterable<Network> networks) {
|
||||
this.novaNetworks = ImmutableSet.copyOf(networks);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getNetworks
|
||||
*/
|
||||
public CreateServerOptions networks(String... networks) {
|
||||
return networks(ImmutableSet.copyOf(networks));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getBlockDeviceMapping
|
||||
*/
|
||||
public CreateServerOptions blockDeviceMapping(Set<BlockDeviceMapping> blockDeviceMapping) {
|
||||
this.blockDeviceMapping = ImmutableSet.copyOf(blockDeviceMapping);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block volumes that should be attached to the instance at boot time.
|
||||
*
|
||||
* @see <a href="http://docs.openstack.org/trunk/openstack-ops/content/attach_block_storage.html">Attach Block Storage<a/>
|
||||
*/
|
||||
public Set<BlockDeviceMapping> getBlockDeviceMapping() {
|
||||
return blockDeviceMapping;
|
||||
public Set<BlockDeviceMapping> getBlockDeviceMappings() {
|
||||
return blockDeviceMappings;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#writeFileToPath
|
||||
* @see CreateServerOptions#writeFileToPath(byte[], String)
|
||||
*/
|
||||
public static CreateServerOptions writeFileToPath(byte[] contents, String path) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return options.writeFileToPath(contents, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#adminPass(String)
|
||||
*/
|
||||
public static CreateServerOptions adminPass(String adminPass) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return options.adminPass(adminPass);
|
||||
|
@ -514,7 +511,7 @@ public class CreateServerOptions implements MapBinder {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see #getKeyPairName()
|
||||
* @see CreateServerOptions#keyPairName(String)
|
||||
*/
|
||||
public static CreateServerOptions keyPairName(String keyName) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
|
@ -522,67 +519,62 @@ public class CreateServerOptions implements MapBinder {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#getSecurityGroupNames
|
||||
* @see CreateServerOptions#securityGroupNames(String...)
|
||||
*/
|
||||
public static CreateServerOptions securityGroupNames(String... groupNames) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
if (new CreateServerOptions().securityGroupNames(groupNames) == CreateServerOptions.class.cast(options.securityGroupNames(groupNames)))
|
||||
System.out.println("They are fucking equal, dump the cast!!!");
|
||||
return CreateServerOptions.class.cast(options.securityGroupNames(groupNames));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#getSecurityGroupNames
|
||||
* @see CreateServerOptions#securityGroupNames(Iterable)
|
||||
*/
|
||||
public static CreateServerOptions securityGroupNames(Iterable<String> groupNames) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return CreateServerOptions.class.cast(options.securityGroupNames(groupNames));
|
||||
return CreateServerOptions.class.cast(new CreateServerOptions().securityGroupNames(groupNames));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#getDiskConfig
|
||||
* @see CreateServerOptions#diskConfig(String)
|
||||
*/
|
||||
public static CreateServerOptions diskConfig(String diskConfig) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return CreateServerOptions.class.cast(options.diskConfig(diskConfig));
|
||||
return CreateServerOptions.class.cast(new CreateServerOptions().diskConfig(diskConfig));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#getNetworks
|
||||
* @see CreateServerOptions#networks(String...)
|
||||
*/
|
||||
public static CreateServerOptions networks(String... networks) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return CreateServerOptions.class.cast(options.networks(networks));
|
||||
return CreateServerOptions.class.cast(new CreateServerOptions().networks(networks));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#getNetworks
|
||||
* @see CreateServerOptions#networks(Iterable)
|
||||
*/
|
||||
public static CreateServerOptions networks(Iterable<String> networks) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return CreateServerOptions.class.cast(options.networks(networks));
|
||||
return CreateServerOptions.class.cast(new CreateServerOptions().networks(networks));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CreateServerOptions#getNetworks
|
||||
* @see CreateServerOptions#novaNetworks(Iterable)
|
||||
*/
|
||||
public static CreateServerOptions novaNetworks(Iterable<Network> networks) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return CreateServerOptions.class.cast(options.novaNetworks(networks));
|
||||
return CreateServerOptions.class.cast(new CreateServerOptions().novaNetworks(networks));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getAvailabilityZone()
|
||||
* @see CreateServerOptions#availabilityZone(String)
|
||||
*/
|
||||
public static CreateServerOptions availabilityZone(String availabilityZone) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return options.availabilityZone(availabilityZone);
|
||||
return new CreateServerOptions().availabilityZone(availabilityZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getBlockDeviceMapping()
|
||||
* @see CreateServerOptions#blockDeviceMappings(Set)
|
||||
*/
|
||||
public static CreateServerOptions blockDeviceMapping(Set<BlockDeviceMapping> blockDeviceMapping) {
|
||||
CreateServerOptions options = new CreateServerOptions();
|
||||
return options.blockDeviceMapping(blockDeviceMapping);
|
||||
public static CreateServerOptions blockDeviceMappings(Set<BlockDeviceMapping> blockDeviceMappings) {
|
||||
return new CreateServerOptions().blockDeviceMappings(blockDeviceMappings);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,9 @@ import static org.testng.Assert.assertTrue;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.openstack.nova.v2_0.domain.BlockDeviceMapping;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Volume;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment;
|
||||
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest;
|
||||
import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
|
||||
import org.jclouds.openstack.nova.v2_0.options.CreateVolumeOptions;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
|
@ -36,7 +34,6 @@ import org.testng.annotations.Test;
|
|||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
|
@ -154,6 +151,7 @@ public class VolumeAttachmentApiLiveTest extends BaseNovaApiLiveTest {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Test(dependsOnMethods = "testCreateVolume")
|
||||
public void testAttachmentAtBoot() {
|
||||
if (volumeApi.isPresent()) {
|
||||
|
@ -188,5 +186,5 @@ public class VolumeAttachmentApiLiveTest extends BaseNovaApiLiveTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -200,8 +200,7 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
|
|||
new ParseCreatedServerTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testCreateServerWithAttachedDiskWhenResponseIs202() throws Exception {
|
||||
|
||||
public void testCreateServerWithBootVolumeWhenResponseIs202() throws Exception {
|
||||
HttpRequest createServer = HttpRequest
|
||||
.builder()
|
||||
.method("POST")
|
||||
|
@ -209,10 +208,9 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
|
|||
.addHeader("Accept", "application/json")
|
||||
.addHeader("X-Auth-Token", authToken)
|
||||
.payload(payloadFromStringWithContentType(
|
||||
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"1241\",\"flavorRef\":\"100\",\"block_device_mapping\":[{\"volume_size\":\"\",\"volume_id\":\"f0c907a5-a26b-48ba-b803-83f6b7450ba5\",\"delete_on_termination\":\"1\",\"device_name\":\"vdb\"}]}}", "application/json"))
|
||||
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"\",\"flavorRef\":\"12345\",\"block_device_mapping_v2\":[{\"volume_size\":100,\"uuid\":\"f0c907a5-a26b-48ba-b803-83f6b7450ba5\",\"destination_type\":\"volume\",\"source_type\":\"image\"}]}}", "application/json"))
|
||||
.build();
|
||||
|
||||
|
||||
HttpResponse createServerResponse = HttpResponse.builder().statusCode(202).message("HTTP/1.1 202 Accepted")
|
||||
.payload(payloadFromResourceWithContentType("/new_server.json", "application/json; charset=UTF-8")).build();
|
||||
|
||||
|
@ -220,12 +218,43 @@ public class ServerApiExpectTest extends BaseNovaApiExpectTest {
|
|||
NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
|
||||
responseWithKeystoneAccess, createServer, createServerResponse);
|
||||
|
||||
BlockDeviceMapping blockDeviceMapping = BlockDeviceMapping.createOptions("f0c907a5-a26b-48ba-b803-83f6b7450ba5", "vdb").deleteOnTermination(true).build();
|
||||
assertEquals(apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").create("test-e92", "1241",
|
||||
"100", new CreateServerOptions().blockDeviceMapping(ImmutableSet.of(blockDeviceMapping))).toString(),
|
||||
BlockDeviceMapping blockDeviceMapping = BlockDeviceMapping.builder()
|
||||
.uuid("f0c907a5-a26b-48ba-b803-83f6b7450ba5").sourceType("image").destinationType("volume")
|
||||
.volumeSize(100).build();
|
||||
|
||||
assertEquals(apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").create("test-e92", "",
|
||||
"12345", new CreateServerOptions().blockDeviceMappings(ImmutableSet.of(blockDeviceMapping))).toString(),
|
||||
new ParseCreatedServerTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testCreateServerWithBootVolumeWhenResponseIs404() throws Exception {
|
||||
HttpRequest createServer = HttpRequest
|
||||
.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/servers")
|
||||
.addHeader("Accept", "application/json")
|
||||
.addHeader("X-Auth-Token", authToken)
|
||||
.payload(payloadFromStringWithContentType(
|
||||
"{\"server\":{\"name\":\"test-e92\",\"imageRef\":\"\",\"flavorRef\":\"12345\",\"block_device_mapping_v2\":[{\"volume_size\":100,\"uuid\":\"f0c907a5-a26b-48ba-b803-83f6b7450ba5\",\"destination_type\":\"volume\",\"source_type\":\"image\"}]}}", "application/json"))
|
||||
.build();
|
||||
|
||||
HttpResponse createServerResponse = HttpResponse.builder().statusCode(404).build();
|
||||
|
||||
NovaApi apiWithNewServer = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
|
||||
responseWithKeystoneAccess, createServer, createServerResponse);
|
||||
|
||||
BlockDeviceMapping blockDeviceMapping = BlockDeviceMapping.builder()
|
||||
.uuid("f0c907a5-a26b-48ba-b803-83f6b7450ba5").sourceType("image")
|
||||
.destinationType("volume").volumeSize(100).build();
|
||||
|
||||
try {
|
||||
apiWithNewServer.getServerApiForZone("az-1.region-a.geo-1").create("test-e92", "", "12345", new CreateServerOptions().blockDeviceMappings(ImmutableSet.of(blockDeviceMapping)));
|
||||
fail("Expected an exception.");
|
||||
} catch (Exception e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateServerWithDiskConfigAuto() throws Exception {
|
||||
HttpRequest createServer = HttpRequest.builder()
|
||||
.method("POST")
|
||||
|
|
|
@ -19,12 +19,11 @@ package org.jclouds.openstack.nova.v2_0.features;
|
|||
import static org.jclouds.openstack.nova.v2_0.domain.Server.Status.ACTIVE;
|
||||
import static org.jclouds.openstack.nova.v2_0.predicates.ServerPredicates.awaitActive;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.BlockDeviceMapping;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Network;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Server;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.ServerCreated;
|
||||
|
@ -34,9 +33,11 @@ import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
|
|||
import org.jclouds.openstack.nova.v2_0.options.RebuildServerOptions;
|
||||
import org.jclouds.openstack.v2_0.domain.Link.Relation;
|
||||
import org.jclouds.openstack.v2_0.domain.Resource;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.v2_0.predicates.LinkPredicates;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
|
@ -132,6 +133,50 @@ public class ServerApiLiveTest extends BaseNovaApiLiveTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test creates a new server with a boot device from an image.
|
||||
*
|
||||
* This needs to be supported by the provider, and is usually not supported.
|
||||
*
|
||||
* TODO: Configurable system properties for flavor/image refs.
|
||||
*/
|
||||
@Test
|
||||
public void testCreateWithBlockDeviceMapping() {
|
||||
String serverId = null;
|
||||
// Rackspace Performance Flavor
|
||||
String flavorRef = "performance1-2";
|
||||
// Rackspace CentOS 6.5 image
|
||||
String imageRef = "3ab30cc6-c503-41d3-8a37-106fda7848a7";
|
||||
for (String zoneId : zones) {
|
||||
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||
ExtensionApi extensionApi = api.getExtensionApiForZone(zoneId);
|
||||
|
||||
// check for the existence of the block mapping v2 boot extension
|
||||
if (extensionApi.get("os-block-device-mapping-v2-boot") != null) {
|
||||
try {
|
||||
BlockDeviceMapping blockDeviceMappings = BlockDeviceMapping.builder()
|
||||
.uuid(imageRef).sourceType("image").destinationType("volume")
|
||||
.volumeSize(100).bootIndex(0).build();
|
||||
|
||||
CreateServerOptions options = CreateServerOptions.Builder
|
||||
.blockDeviceMappings(ImmutableSet.of(blockDeviceMappings));
|
||||
|
||||
ServerCreated server = serverApi.create(hostName, "", flavorRef, options);
|
||||
serverId = server.getId();
|
||||
|
||||
awaitActive(serverApi).apply(server.getId());
|
||||
|
||||
Server serverCheck = serverApi.get(serverId);
|
||||
assertEquals(serverCheck.getStatus(), ACTIVE);
|
||||
} finally {
|
||||
if (serverId != null) {
|
||||
serverApi.delete(serverId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateInWrongAvailabilityZone() {
|
||||
String serverId = null;
|
||||
|
@ -154,9 +199,7 @@ public class ServerApiLiveTest extends BaseNovaApiLiveTest {
|
|||
|
||||
@Test
|
||||
public void testRebuildServer() {
|
||||
|
||||
String serverId = null;
|
||||
|
||||
for (String zoneId : zones) {
|
||||
ServerApi serverApi = api.getServerApiForZone(zoneId);
|
||||
try {
|
||||
|
@ -213,6 +256,6 @@ public class ServerApiLiveTest extends BaseNovaApiLiveTest {
|
|||
|
||||
private void checkServer(Server server) {
|
||||
checkResource(server);
|
||||
assertFalse(server.getAddresses().isEmpty());
|
||||
assertNotNull(server.getFlavor());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -279,6 +279,22 @@
|
|||
"namespace": "http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1",
|
||||
"alias": "os-availability-zone",
|
||||
"description": "1. Add availability_zone to the Create Server v1.1 API.\n 2. Add availability zones describing.\n "
|
||||
},
|
||||
{
|
||||
"updated":"2013-07-08T00:00:00+00:00",
|
||||
"name":"BlockDeviceMappingV2Boot",
|
||||
"links":[],
|
||||
"namespace":"http://docs.openstack.org/compute/ext/block_device_mapping_v2_boot/api/v2",
|
||||
"alias":"os-block-device-mapping-v2-boot",
|
||||
"description":"Allow boot with the new BDM data format."
|
||||
},
|
||||
{
|
||||
"alias": "os-volume-attachment-update",
|
||||
"description": "Support for updating a volume attachment.",
|
||||
"links": [],
|
||||
"name": "VolumeAttachmentUpdate",
|
||||
"namespace": "http://docs.openstack.org/compute/ext/os-volume-attachment-update/api/v2",
|
||||
"updated": "2013-06-20T00:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -39,4 +39,4 @@
|
|||
"metadata": {},
|
||||
"OS-DCF:diskConfig": "AUTO"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,4 +37,4 @@
|
|||
"id": 71752,
|
||||
"metadata": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,4 +71,4 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue