mirror of https://github.com/apache/jclouds.git
Adding CreateVolume and CreateSnapshot options and improving live tests accordingly
This commit is contained in:
parent
01de74236b
commit
58d4de4bbe
|
@ -77,7 +77,7 @@ public class Volume {
|
||||||
private int size;
|
private int size;
|
||||||
private String zone;
|
private String zone;
|
||||||
private Date created;
|
private Date created;
|
||||||
private Set<Attachment> attachments = Sets.newLinkedHashSet();
|
private Set<VolumeAttachment> attachments = Sets.newLinkedHashSet();
|
||||||
private String volumeType;
|
private String volumeType;
|
||||||
private String snapshotId;
|
private String snapshotId;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -109,7 +109,7 @@ public class Volume {
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public T attachments(Set<Attachment> attachments) {
|
public T attachments(Set<VolumeAttachment> attachments) {
|
||||||
this.attachments = attachments;
|
this.attachments = attachments;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ public class Volume {
|
||||||
private final String zone;
|
private final String zone;
|
||||||
@SerializedName(value="createdAt")
|
@SerializedName(value="createdAt")
|
||||||
private final Date created;
|
private final Date created;
|
||||||
private final Set<Attachment> attachments;
|
private final Set<VolumeAttachment> attachments;
|
||||||
private final String volumeType;
|
private final String volumeType;
|
||||||
private final String snapshotId;
|
private final String snapshotId;
|
||||||
@SerializedName(value="displayName")
|
@SerializedName(value="displayName")
|
||||||
|
@ -229,7 +229,7 @@ public class Volume {
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public Set<Attachment> getAttachments() {
|
public Set<VolumeAttachment> getAttachments() {
|
||||||
return Collections.unmodifiableSet(this.attachments);
|
return Collections.unmodifiableSet(this.attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import com.google.common.base.Objects.ToStringHelper;
|
||||||
/**
|
/**
|
||||||
* An Openstack Nova Volume Attachment
|
* An Openstack Nova Volume Attachment
|
||||||
*/
|
*/
|
||||||
public class Attachment {
|
public class VolumeAttachment {
|
||||||
|
|
||||||
public static Builder<?> builder() {
|
public static Builder<?> builder() {
|
||||||
return new ConcreteBuilder();
|
return new ConcreteBuilder();
|
||||||
|
@ -64,11 +64,11 @@ public class Attachment {
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Attachment build() {
|
public VolumeAttachment build() {
|
||||||
return new Attachment(this);
|
return new VolumeAttachment(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T fromAttachment(Attachment in) {
|
public T fromAttachment(VolumeAttachment in) {
|
||||||
return this
|
return this
|
||||||
.id(in.getId())
|
.id(in.getId())
|
||||||
.volumeId(in.getVolumeId())
|
.volumeId(in.getVolumeId())
|
||||||
|
@ -91,7 +91,7 @@ public class Attachment {
|
||||||
private final String serverId;
|
private final String serverId;
|
||||||
private final String device;
|
private final String device;
|
||||||
|
|
||||||
protected Attachment(Builder<?> builder) {
|
protected VolumeAttachment(Builder<?> builder) {
|
||||||
this.id = builder.id;
|
this.id = builder.id;
|
||||||
this.volumeId = builder.volumeId;
|
this.volumeId = builder.volumeId;
|
||||||
this.serverId = builder.serverId;
|
this.serverId = builder.serverId;
|
||||||
|
@ -135,7 +135,7 @@ public class Attachment {
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) return true;
|
if (this == obj) return true;
|
||||||
if (obj == null || getClass() != obj.getClass()) return false;
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
Attachment that = Attachment.class.cast(obj);
|
VolumeAttachment that = VolumeAttachment.class.cast(obj);
|
||||||
return Objects.equal(this.id, that.id)
|
return Objects.equal(this.id, that.id)
|
||||||
&& Objects.equal(this.volumeId, that.volumeId)
|
&& Objects.equal(this.volumeId, that.volumeId)
|
||||||
&& Objects.equal(this.serverId, that.serverId)
|
&& Objects.equal(this.serverId, that.serverId)
|
|
@ -29,7 +29,7 @@ import com.google.gson.annotations.SerializedName;
|
||||||
/**
|
/**
|
||||||
* An Openstack Nova Volume Snapshot
|
* An Openstack Nova Volume Snapshot
|
||||||
*/
|
*/
|
||||||
public class Snapshot {
|
public class VolumeSnapshot {
|
||||||
|
|
||||||
public static Builder<?> builder() {
|
public static Builder<?> builder() {
|
||||||
return new ConcreteBuilder();
|
return new ConcreteBuilder();
|
||||||
|
@ -44,7 +44,7 @@ public class Snapshot {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String volumeId;
|
private String volumeId;
|
||||||
private String status;
|
private Volume.Status status;
|
||||||
private int size;
|
private int size;
|
||||||
private Date created;
|
private Date created;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -60,7 +60,7 @@ public class Snapshot {
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public T status(String status) {
|
public T status(Volume.Status status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
@ -85,11 +85,11 @@ public class Snapshot {
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Snapshot build() {
|
public VolumeSnapshot build() {
|
||||||
return new Snapshot(this);
|
return new VolumeSnapshot(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T fromSnapshot(Snapshot in) {
|
public T fromSnapshot(VolumeSnapshot in) {
|
||||||
return this
|
return this
|
||||||
.id(in.getId())
|
.id(in.getId())
|
||||||
.volumeId(in.getVolumeId())
|
.volumeId(in.getVolumeId())
|
||||||
|
@ -112,7 +112,7 @@ public class Snapshot {
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
private final String volumeId;
|
private final String volumeId;
|
||||||
private final String status;
|
private final Volume.Status status;
|
||||||
private final int size;
|
private final int size;
|
||||||
@SerializedName(value="createdAt")
|
@SerializedName(value="createdAt")
|
||||||
private final Date created;
|
private final Date created;
|
||||||
|
@ -121,7 +121,7 @@ public class Snapshot {
|
||||||
@SerializedName(value="displayDescription")
|
@SerializedName(value="displayDescription")
|
||||||
private final String description;
|
private final String description;
|
||||||
|
|
||||||
protected Snapshot(Builder<?> builder) {
|
protected VolumeSnapshot(Builder<?> builder) {
|
||||||
this.id = builder.id;
|
this.id = builder.id;
|
||||||
this.volumeId = builder.volumeId;
|
this.volumeId = builder.volumeId;
|
||||||
this.status = builder.status;
|
this.status = builder.status;
|
||||||
|
@ -148,7 +148,7 @@ public class Snapshot {
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getStatus() {
|
public Volume.Status getStatus() {
|
||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ public class Snapshot {
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) return true;
|
if (this == obj) return true;
|
||||||
if (obj == null || getClass() != obj.getClass()) return false;
|
if (obj == null || getClass() != obj.getClass()) return false;
|
||||||
Snapshot that = Snapshot.class.cast(obj);
|
VolumeSnapshot that = VolumeSnapshot.class.cast(obj);
|
||||||
return Objects.equal(this.id, that.id)
|
return Objects.equal(this.id, that.id)
|
||||||
&& Objects.equal(this.volumeId, that.volumeId)
|
&& Objects.equal(this.volumeId, that.volumeId)
|
||||||
&& Objects.equal(this.status, that.status)
|
&& Objects.equal(this.status, that.status)
|
|
@ -30,12 +30,16 @@ import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.openstack.filters.AuthenticateRequest;
|
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Attachment;
|
import org.jclouds.openstack.nova.v1_1.domain.VolumeAttachment;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Snapshot;
|
import org.jclouds.openstack.nova.v1_1.domain.VolumeSnapshot;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateVolumeSnapshotOptions;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateVolumeOptions;
|
||||||
import org.jclouds.openstack.services.Extension;
|
import org.jclouds.openstack.services.Extension;
|
||||||
import org.jclouds.openstack.services.ServiceType;
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
import org.jclouds.rest.annotations.ExceptionParser;
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
import org.jclouds.rest.annotations.MapBinder;
|
||||||
|
import org.jclouds.rest.annotations.Payload;
|
||||||
import org.jclouds.rest.annotations.PayloadParam;
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.SelectJson;
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
@ -99,10 +103,12 @@ public interface VolumeAsyncClient {
|
||||||
* @return the new Snapshot
|
* @return the new Snapshot
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/os-volumes/")
|
@Path("/os-volumes")
|
||||||
@SelectJson("volume")
|
@SelectJson("volume")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<Volume> createVolume(@PayloadParam("volume") Volume createVolume);
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@MapBinder(CreateVolumeOptions.class)
|
||||||
|
ListenableFuture<Volume> createVolume(@PayloadParam("size") int sizeGB, CreateVolumeOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a volume.
|
* Delete a volume.
|
||||||
|
@ -111,7 +117,6 @@ public interface VolumeAsyncClient {
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("/os-volumes/{id}")
|
@Path("/os-volumes/{id}")
|
||||||
@SelectJson("volumes")
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||||
ListenableFuture<Boolean> deleteVolume(@PathParam("id") String volumeId);
|
ListenableFuture<Boolean> deleteVolume(@PathParam("id") String volumeId);
|
||||||
|
@ -126,7 +131,7 @@ public interface VolumeAsyncClient {
|
||||||
@SelectJson("volumeAttachments")
|
@SelectJson("volumeAttachments")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
ListenableFuture<Set<Attachment>> listAttachments(@PathParam("server_id") String serverId);
|
ListenableFuture<Set<VolumeAttachment>> listAttachments(@PathParam("server_id") String serverId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a specific attached volume.
|
* Get a specific attached volume.
|
||||||
|
@ -138,7 +143,7 @@ public interface VolumeAsyncClient {
|
||||||
@SelectJson("volumeAttachment")
|
@SelectJson("volumeAttachment")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
ListenableFuture<Attachment> getAttachment(@PathParam("server_id") String serverId, @PathParam("id") String volumeId);
|
ListenableFuture<VolumeAttachment> getAttachment(@PathParam("server_id") String serverId, @PathParam("id") String volumeId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach a volume to an instance
|
* Attach a volume to an instance
|
||||||
|
@ -146,11 +151,14 @@ public interface VolumeAsyncClient {
|
||||||
* @return the new Attachment
|
* @return the new Attachment
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
@Path("/servers/{server_id}/os-volume_attachments/")
|
@Path("/servers/{server_id}/os-volume_attachments")
|
||||||
@SelectJson("volumeAttachment")
|
@SelectJson("volumeAttachment")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<Attachment> attachVolume(@PathParam("server_id") String serverId, @PayloadParam("attachment") Attachment attachVolume);
|
@Payload("%7B\"volumeAttachment\":%7B\"volumeId\":\"{id}\",\"device\":\"{device}\"%7D%7D")
|
||||||
|
ListenableFuture<VolumeAttachment> attachVolume(@PathParam("server_id") String serverId,
|
||||||
|
@PayloadParam("id") String volumeId,
|
||||||
|
@PayloadParam("device") String device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach a Volume from an instance.
|
* Detach a Volume from an instance.
|
||||||
|
@ -170,10 +178,10 @@ public interface VolumeAsyncClient {
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("/os-snapshots")
|
@Path("/os-snapshots")
|
||||||
@SelectJson("volumes")
|
@SelectJson("snapshots")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
ListenableFuture<Set<Snapshot>> listSnapshots();
|
ListenableFuture<Set<VolumeSnapshot>> listSnapshots();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a summary list of snapshots.
|
* Returns a summary list of snapshots.
|
||||||
|
@ -185,7 +193,7 @@ public interface VolumeAsyncClient {
|
||||||
@SelectJson("snapshots")
|
@SelectJson("snapshots")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
ListenableFuture<Set<Snapshot>> listSnapshotsInDetail();
|
ListenableFuture<Set<VolumeSnapshot>> listSnapshotsInDetail();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return data about the given snapshot.
|
* Return data about the given snapshot.
|
||||||
|
@ -194,21 +202,23 @@ public interface VolumeAsyncClient {
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("/os-snapshots/{id}")
|
@Path("/os-snapshots/{id}")
|
||||||
@SelectJson("snapshots")
|
@SelectJson("snapshot")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
ListenableFuture<Snapshot> getSnapshot(@PathParam("id") String snapshotId);
|
ListenableFuture<VolumeSnapshot> getSnapshot(@PathParam("id") String snapshotId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Snapshot
|
* Creates a new Snapshot
|
||||||
*
|
*
|
||||||
* @return the new Snapshot
|
* @return the new Snapshot
|
||||||
*/
|
*/
|
||||||
@GET
|
@POST
|
||||||
@Path("/os-snapshots/detail")
|
@Path("/os-snapshots")
|
||||||
@SelectJson("snapshots")
|
@SelectJson("snapshot")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<Snapshot> createSnapshot(@PayloadParam("snapshot") Snapshot createSnapshot);
|
@MapBinder(CreateVolumeSnapshotOptions.class)
|
||||||
|
ListenableFuture<VolumeSnapshot> createSnapshot(@PayloadParam("volume_id") String volumeId, CreateVolumeSnapshotOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a snapshot.
|
* Delete a snapshot.
|
||||||
|
|
|
@ -22,9 +22,11 @@ import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Attachment;
|
import org.jclouds.openstack.nova.v1_1.domain.VolumeAttachment;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Snapshot;
|
import org.jclouds.openstack.nova.v1_1.domain.VolumeSnapshot;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateVolumeSnapshotOptions;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.options.CreateVolumeOptions;
|
||||||
import org.jclouds.openstack.services.Extension;
|
import org.jclouds.openstack.services.Extension;
|
||||||
import org.jclouds.openstack.services.ServiceType;
|
import org.jclouds.openstack.services.ServiceType;
|
||||||
|
|
||||||
|
@ -64,12 +66,12 @@ public interface VolumeClient {
|
||||||
*
|
*
|
||||||
* @return the new Snapshot
|
* @return the new Snapshot
|
||||||
*/
|
*/
|
||||||
Volume createVolume(Volume createVolume);
|
Volume createVolume(int sizeGB, CreateVolumeOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a snapshot.
|
* Delete a snapshot.
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if successful
|
||||||
*/
|
*/
|
||||||
Boolean deleteVolume(String volumeId);
|
Boolean deleteVolume(String volumeId);
|
||||||
|
|
||||||
|
@ -78,26 +80,26 @@ public interface VolumeClient {
|
||||||
*
|
*
|
||||||
* @return all Floating IPs
|
* @return all Floating IPs
|
||||||
*/
|
*/
|
||||||
Set<Attachment> listAttachments(String serverId);
|
Set<VolumeAttachment> listAttachments(String serverId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a specific attached volume.
|
* Get a specific attached volume.
|
||||||
*
|
*
|
||||||
* @return data about the given volume attachment.
|
* @return data about the given volume attachment.
|
||||||
*/
|
*/
|
||||||
Attachment getAttachment(String serverId, String volumeId);
|
VolumeAttachment getAttachment(String serverId, String volumeId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach a volume to an instance
|
* Attach a volume to an instance
|
||||||
*
|
*
|
||||||
* @return a new Volume
|
* @return data about the new volume attachment
|
||||||
*/
|
*/
|
||||||
Attachment attachVolume(String serverId, Attachment attachVolume);
|
VolumeAttachment attachVolume(String serverId, String volumeId, String device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach a Volume from an instance.
|
* Detach a Volume from an instance.
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if successful
|
||||||
*/
|
*/
|
||||||
Boolean detachVolume(String server_id, String volumeId);
|
Boolean detachVolume(String server_id, String volumeId);
|
||||||
|
|
||||||
|
@ -106,33 +108,33 @@ public interface VolumeClient {
|
||||||
*
|
*
|
||||||
* @return the list of snapshots
|
* @return the list of snapshots
|
||||||
*/
|
*/
|
||||||
Set<Snapshot> listSnapshots();
|
Set<VolumeSnapshot> listSnapshots();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a summary list of snapshots.
|
* Returns a summary list of snapshots.
|
||||||
*
|
*
|
||||||
* @return the list of snapshots
|
* @return the list of snapshots
|
||||||
*/
|
*/
|
||||||
Set<Snapshot> listSnapshotsInDetail();
|
Set<VolumeSnapshot> listSnapshotsInDetail();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return data about the given snapshot.
|
* Return data about the given snapshot.
|
||||||
*
|
*
|
||||||
* @return details of a specific snapshot.
|
* @return details of a specific snapshot.
|
||||||
*/
|
*/
|
||||||
Snapshot getSnapshot(String snapshotId);
|
VolumeSnapshot getSnapshot(String snapshotId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Snapshot
|
* Creates a new Snapshot
|
||||||
*
|
*
|
||||||
* @return the new Snapshot
|
* @return the new Snapshot
|
||||||
*/
|
*/
|
||||||
Snapshot createSnapshot(Snapshot createSnapshot);
|
VolumeSnapshot createSnapshot(String volumeId, CreateVolumeSnapshotOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a snapshot.
|
* Delete a snapshot.
|
||||||
*
|
*
|
||||||
* @return
|
* @return true if successful
|
||||||
*/
|
*/
|
||||||
Boolean deleteSnapshot(String snapshotId);
|
Boolean deleteSnapshot(String snapshotId);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,224 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.openstack.nova.v1_1.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
import static com.google.common.base.Objects.toStringHelper;
|
||||||
|
import static com.google.common.base.Preconditions.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.encryption.internal.Base64;
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup;
|
||||||
|
import org.jclouds.rest.MapBinder;
|
||||||
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
|
import org.jclouds.util.Preconditions2;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
public class CreateVolumeOptions implements MapBinder {
|
||||||
|
public static final CreateVolumeOptions NONE = new CreateVolumeOptions();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BindToJsonPayload jsonBinder;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private String volumeType;
|
||||||
|
private String availabilityZone;
|
||||||
|
private String snapshotId;
|
||||||
|
private Map<String, String> metadata = ImmutableMap.of();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
|
||||||
|
Map<String, Object> image = Maps.newHashMap();
|
||||||
|
image.putAll(postParams);
|
||||||
|
if (name != null)
|
||||||
|
image.put("display_name", name);
|
||||||
|
if (description != null)
|
||||||
|
image.put("display_description", description);
|
||||||
|
if (!metadata.isEmpty())
|
||||||
|
image.put("metadata", metadata);
|
||||||
|
return jsonBinder.bindToRequest(request, ImmutableMap.of("volume", image));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
|
||||||
|
throw new IllegalStateException("CreateVolume is a POST operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(object instanceof CreateVolumeOptions)) return false;
|
||||||
|
final CreateVolumeOptions other = CreateVolumeOptions.class.cast(object);
|
||||||
|
return equal(volumeType, other.volumeType) && equal(availabilityZone, other.availabilityZone) && equal(snapshotId, other.snapshotId)
|
||||||
|
&& equal(name, other.name) && equal(description, other.description) && equal(metadata, other.metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(volumeType, availabilityZone, snapshotId, name, description, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return toStringHelper("").add("volumeType", volumeType).add("availabilityZone", availabilityZone)
|
||||||
|
.add("snapshotId", snapshotId).add("name", name).add("description", description).add("metadata", metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom cloud server metadata can also be supplied at launch time. This
|
||||||
|
* metadata is stored in the API system where it is retrievable by querying
|
||||||
|
* the API for server status. The maximum size of the metadata key and value
|
||||||
|
* is each 255 bytes and the maximum number of key-value pairs that can be
|
||||||
|
* supplied per volume is 5.
|
||||||
|
*/
|
||||||
|
public CreateVolumeOptions metadata(Map<String, String> metadata) {
|
||||||
|
checkNotNull(metadata, "metadata");
|
||||||
|
checkArgument(metadata.size() <= 5,
|
||||||
|
"you cannot have more then 5 metadata values. You specified: " + metadata.size());
|
||||||
|
for (Entry<String, String> entry : metadata.entrySet()) {
|
||||||
|
checkArgument(
|
||||||
|
entry.getKey().getBytes().length < 255,
|
||||||
|
String.format("maximum length of metadata key is 255 bytes. Key specified %s is %d bytes",
|
||||||
|
entry.getKey(), entry.getKey().getBytes().length));
|
||||||
|
checkArgument(entry.getKey().getBytes().length < 255, String.format(
|
||||||
|
"maximum length of metadata value is 255 bytes. Value specified for %s (%s) is %d bytes",
|
||||||
|
entry.getKey(), entry.getValue(), entry.getValue().getBytes().length));
|
||||||
|
}
|
||||||
|
this.metadata = ImmutableMap.copyOf(metadata);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateVolumeOptions name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateVolumeOptions description(String description) {
|
||||||
|
this.description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateVolumeOptions volumeType(String volumeType) {
|
||||||
|
this.volumeType = volumeType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateVolumeOptions availabilityZone(String availabilityZone) {
|
||||||
|
this.availabilityZone = availabilityZone;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateVolumeOptions snapshotId(String snapshotId) {
|
||||||
|
this.snapshotId = snapshotId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVolumeType() {
|
||||||
|
return volumeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAvailabilityZone() {
|
||||||
|
return availabilityZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSnapshotId() {
|
||||||
|
return snapshotId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeOptions#getName()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeOptions name(String name) {
|
||||||
|
return new CreateVolumeOptions().name(name);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeOptions#getDescription()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeOptions description(String description) {
|
||||||
|
return new CreateVolumeOptions().description(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeOptions#getVolumeType()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeOptions volumeType(String volumeType) {
|
||||||
|
return new CreateVolumeOptions().volumeType(volumeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeOptions#getAvailabilityZone()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeOptions availabilityZone(String availabilityZone) {
|
||||||
|
return new CreateVolumeOptions().availabilityZone(availabilityZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeOptions#getSnapshotId()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeOptions snapshotId(String snapshotId) {
|
||||||
|
return new CreateVolumeOptions().snapshotId(snapshotId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeOptions#getMetadata()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeOptions metadata(Map<String, String> metadata) {
|
||||||
|
return new CreateVolumeOptions().metadata(metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds 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.openstack.nova.v1_1.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Objects.equal;
|
||||||
|
import static com.google.common.base.Objects.toStringHelper;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpRequest;
|
||||||
|
import org.jclouds.rest.MapBinder;
|
||||||
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adam Lowe
|
||||||
|
*/
|
||||||
|
public class CreateVolumeSnapshotOptions implements MapBinder {
|
||||||
|
public static final CreateVolumeSnapshotOptions NONE = new CreateVolumeSnapshotOptions();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BindToJsonPayload jsonBinder;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private boolean force = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
|
||||||
|
Map<String, String> data = Maps.newHashMap(postParams);
|
||||||
|
if (name != null)
|
||||||
|
data.put("display_name", name);
|
||||||
|
if (description != null)
|
||||||
|
data.put("display_description", description);
|
||||||
|
if (force)
|
||||||
|
data.put("force", "true");
|
||||||
|
return jsonBinder.bindToRequest(request, ImmutableMap.of("snapshot", data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
|
||||||
|
throw new IllegalStateException("CreateSnapshot is a POST operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(object instanceof CreateVolumeSnapshotOptions)) return false;
|
||||||
|
final CreateVolumeSnapshotOptions other = CreateVolumeSnapshotOptions.class.cast(object);
|
||||||
|
return equal(name, other.name) && equal(description, other.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(name, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ToStringHelper string() {
|
||||||
|
return toStringHelper("").add("name", name).add("description", description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return string().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateVolumeSnapshotOptions name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateVolumeSnapshotOptions description(String description) {
|
||||||
|
this.description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateVolumeSnapshotOptions force() {
|
||||||
|
this.force = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isForce() {
|
||||||
|
return force;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeSnapshotOptions#getName()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeSnapshotOptions name(String name) {
|
||||||
|
return new CreateVolumeSnapshotOptions().name(name);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeSnapshotOptions#getDescription()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeSnapshotOptions description(String description) {
|
||||||
|
return new CreateVolumeSnapshotOptions().description(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CreateVolumeSnapshotOptions#isForce()
|
||||||
|
*/
|
||||||
|
public static CreateVolumeSnapshotOptions force() {
|
||||||
|
return new CreateVolumeSnapshotOptions().force();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,21 +23,26 @@ import static org.testng.Assert.*;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.openstack.domain.Resource;
|
import org.jclouds.openstack.domain.Resource;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Attachment;
|
import org.jclouds.openstack.nova.v1_1.domain.VolumeAttachment;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
import org.jclouds.openstack.nova.v1_1.domain.VolumeSnapshot;
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.SimpleTenantUsage;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Snapshot;
|
|
||||||
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
import org.jclouds.openstack.nova.v1_1.domain.Volume;
|
||||||
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.jclouds.openstack.nova.v1_1.options.CreateVolumeSnapshotOptions;
|
||||||
import org.testng.annotations.BeforeMethod;
|
import org.jclouds.openstack.nova.v1_1.options.CreateVolumeOptions;
|
||||||
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.testng.annotations.AfterGroups;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of SimpleTenantUsageClient
|
* Tests behavior of VolumeClient
|
||||||
|
*
|
||||||
|
* Cannot create snapshots whilst a volume is attached, hence single threaded
|
||||||
*
|
*
|
||||||
* @author Adam Lowe
|
* @author Adam Lowe
|
||||||
*/
|
*/
|
||||||
|
@ -47,8 +52,13 @@ public class VolumeClientLiveTest extends BaseNovaClientLiveTest {
|
||||||
private VolumeClient client;
|
private VolumeClient client;
|
||||||
private String zone;
|
private String zone;
|
||||||
|
|
||||||
@BeforeMethod(alwaysRun = true)
|
private Volume testVolume;
|
||||||
public void setUpClient() {
|
private VolumeSnapshot testSnapshot;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = { "integration", "live" })
|
||||||
|
@Override
|
||||||
|
public void setupContext() {
|
||||||
|
super.setupContext();
|
||||||
zone = Iterables.getFirst(novaContext.getApi().getConfiguredZones(), "nova");
|
zone = Iterables.getFirst(novaContext.getApi().getConfiguredZones(), "nova");
|
||||||
Optional<VolumeClient> optClient = novaContext.getApi().getVolumeExtensionForZone(zone);
|
Optional<VolumeClient> optClient = novaContext.getApi().getVolumeExtensionForZone(zone);
|
||||||
if (optClient.isPresent()) {
|
if (optClient.isPresent()) {
|
||||||
|
@ -56,72 +66,204 @@ public class VolumeClientLiveTest extends BaseNovaClientLiveTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterGroups(groups = "live", alwaysRun = true)
|
||||||
|
@Override
|
||||||
|
protected void tearDown() {
|
||||||
|
if (client != null) {
|
||||||
|
if (testSnapshot != null) {
|
||||||
|
final String snapshotId = testSnapshot.getId();
|
||||||
|
assertTrue(client.deleteSnapshot(snapshotId));
|
||||||
|
assertTrue(new RetryablePredicate<VolumeClient>(new Predicate<VolumeClient>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(VolumeClient volumeClient) {
|
||||||
|
return client.getSnapshot(snapshotId) == null;
|
||||||
|
}
|
||||||
|
}, 30 * 1000L).apply(client));
|
||||||
|
}
|
||||||
|
if (testVolume != null) {
|
||||||
|
final String volumeId = testVolume.getId();
|
||||||
|
assertTrue(client.deleteVolume(volumeId));
|
||||||
|
assertTrue(new RetryablePredicate<VolumeClient>(new Predicate<VolumeClient>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(VolumeClient volumeClient) {
|
||||||
|
return client.getVolume(volumeId) == null;
|
||||||
|
}
|
||||||
|
}, 180 * 1000L).apply(client));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateVolume() throws Exception {
|
||||||
|
testVolume = client.createVolume(1, CreateVolumeOptions.Builder.name("jclouds-test-volume").description("description of test volume").availabilityZone(zone));
|
||||||
|
for (int i=0; i<100 && testVolume.getStatus() == Volume.Status.CREATING; i++) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
testVolume = client.getVolume(testVolume.getId());
|
||||||
|
}
|
||||||
|
assertEquals(testVolume.getStatus(), Volume.Status.AVAILABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateVolume")
|
||||||
public void testListVolumes() throws Exception {
|
public void testListVolumes() throws Exception {
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
Set<Volume> volumes = client.listVolumes();
|
Set<Volume> volumes = client.listVolumes();
|
||||||
assertNotNull(volumes);
|
assertNotNull(volumes);
|
||||||
|
boolean foundIt = false;
|
||||||
for (Volume vol : volumes) {
|
for (Volume vol : volumes) {
|
||||||
Volume details = client.getVolume(vol.getId());
|
Volume details = client.getVolume(vol.getId());
|
||||||
assertNotNull(details);
|
assertNotNull(details);
|
||||||
|
if (Objects.equal(details.getId(), testVolume.getId())) {
|
||||||
|
foundIt = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
assertTrue(foundIt, "Failed to find the volume we created in listVolumes() response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateVolume")
|
||||||
public void testListVolumesInDetail() throws Exception {
|
public void testListVolumesInDetail() throws Exception {
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
Set<Volume> volumes = client.listVolumesInDetail();
|
Set<Volume> volumes = client.listVolumesInDetail();
|
||||||
assertNotNull(volumes);
|
assertNotNull(volumes);
|
||||||
|
assertTrue(volumes.contains(testVolume));
|
||||||
|
boolean foundIt = false;
|
||||||
for (Volume vol : volumes) {
|
for (Volume vol : volumes) {
|
||||||
Volume details = client.getVolume(vol.getId());
|
Volume details = client.getVolume(vol.getId());
|
||||||
assertNotNull(details);
|
assertNotNull(details);
|
||||||
assertEquals(details, vol);
|
|
||||||
assertNotNull(details.getId());
|
assertNotNull(details.getId());
|
||||||
assertNotNull(details.getStatus());
|
|
||||||
assertTrue(details.getSize() > -1);
|
|
||||||
assertNotNull(details.getCreated());
|
assertNotNull(details.getCreated());
|
||||||
|
assertTrue(details.getSize() > -1);
|
||||||
|
|
||||||
|
assertEquals(details.getId(), vol.getId());
|
||||||
|
assertEquals(details.getSize(), vol.getSize());
|
||||||
|
assertEquals(details.getName(), vol.getName());
|
||||||
|
assertEquals(details.getDescription(), vol.getDescription());
|
||||||
|
assertEquals(details.getCreated(), vol.getCreated());
|
||||||
|
if (Objects.equal(details.getId(), testVolume.getId())) {
|
||||||
|
foundIt = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
assertTrue(foundIt, "Failed to find the volume we previously created in listVolumesInDetail() response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateVolume")
|
||||||
|
public void testCreateSnapshot() throws Exception {
|
||||||
|
if (client != null) {
|
||||||
|
testSnapshot = client.createSnapshot(testVolume.getId(), CreateVolumeSnapshotOptions.Builder.name("jclouds-live-test").description("jclouds live test snapshot").force());
|
||||||
|
assertNotNull(testSnapshot);
|
||||||
|
assertNotNull(testSnapshot.getId());
|
||||||
|
final String snapshotId = testSnapshot.getId();
|
||||||
|
assertNotNull(testSnapshot.getStatus());
|
||||||
|
assertTrue(testSnapshot.getSize() > -1);
|
||||||
|
assertNotNull(testSnapshot.getCreated());
|
||||||
|
|
||||||
|
assertTrue(new RetryablePredicate<VolumeClient>(new Predicate<VolumeClient>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(VolumeClient volumeClient) {
|
||||||
|
return client.getSnapshot(snapshotId).getStatus() == Volume.Status.AVAILABLE;
|
||||||
|
}
|
||||||
|
}, 30 * 1000L).apply(client));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateSnapshot")
|
||||||
public void testListSnapshots() throws Exception {
|
public void testListSnapshots() throws Exception {
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
Set<Snapshot> snapshots = client.listSnapshots();
|
Set<VolumeSnapshot> snapshots = client.listSnapshots();
|
||||||
assertNotNull(snapshots);
|
assertNotNull(snapshots);
|
||||||
for (Snapshot snap : snapshots) {
|
boolean foundIt = false;
|
||||||
Snapshot details = client.getSnapshot(snap.getId());
|
for (VolumeSnapshot snap : snapshots) {
|
||||||
|
VolumeSnapshot details = client.getSnapshot(snap.getId());
|
||||||
|
if (Objects.equal(snap.getVolumeId(), testVolume.getId())) {
|
||||||
|
foundIt = true;
|
||||||
|
}
|
||||||
assertNotNull(details);
|
assertNotNull(details);
|
||||||
assertNotNull(details.getId());
|
assertEquals(details.getId(), snap.getId());
|
||||||
|
assertEquals(details.getVolumeId(), snap.getVolumeId());
|
||||||
}
|
}
|
||||||
|
assertTrue(foundIt, "Failed to find the snapshot we previously created in listSnapshots() response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreateSnapshot")
|
||||||
public void testListSnapshotsInDetail() throws Exception {
|
public void testListSnapshotsInDetail() throws Exception {
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
Set<Snapshot> snapshots = client.listSnapshotsInDetail();
|
Set<VolumeSnapshot> snapshots = client.listSnapshotsInDetail();
|
||||||
assertNotNull(snapshots);
|
assertNotNull(snapshots);
|
||||||
for (Snapshot snap : snapshots) {
|
boolean foundIt = false;
|
||||||
Snapshot details = client.getSnapshot(snap.getId());
|
for (VolumeSnapshot snap : snapshots) {
|
||||||
assertNotNull(details);
|
VolumeSnapshot details = client.getSnapshot(snap.getId());
|
||||||
assertEquals(details, snap);
|
if (Objects.equal(snap.getVolumeId(), testVolume.getId())) {
|
||||||
|
foundIt = true;
|
||||||
|
assertSame(details, testSnapshot);
|
||||||
|
}
|
||||||
|
assertSame(details, snap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertTrue(foundIt, "Failed to find the snapshot we created in listSnapshotsInDetail() response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListAttachments() throws Exception {
|
private void assertSame(VolumeSnapshot a, VolumeSnapshot b) {
|
||||||
|
assertNotNull(a);
|
||||||
|
assertNotNull(b);
|
||||||
|
assertEquals(a.getId(), b.getId());
|
||||||
|
assertEquals(a.getDescription(), b.getDescription());
|
||||||
|
assertEquals(a.getName(), b.getName());
|
||||||
|
assertEquals(a.getVolumeId(), b.getVolumeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(enabled=false, dependsOnMethods = "testCreateVolume") // disabled as it alters an existing server
|
||||||
|
public void testAttachments() throws Exception {
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
Set<Resource> servers = novaContext.getApi().getServerClientForZone(zone).listServers();
|
Set<Resource> servers = novaContext.getApi().getServerClientForZone(zone).listServers();
|
||||||
if (!servers.isEmpty()) {
|
if (!servers.isEmpty()) {
|
||||||
String serverId = Iterables.getFirst(servers, null).getId();
|
final String serverId = Iterables.getFirst(servers, null).getId();
|
||||||
Set<Attachment> attachments = client.listAttachments(serverId);
|
Set<VolumeAttachment> attachments = client.listAttachments(serverId);
|
||||||
assertNotNull(attachments);
|
assertNotNull(attachments);
|
||||||
assertTrue(attachments.size() > 0);
|
final int before = attachments.size();
|
||||||
for (Attachment att : attachments) {
|
|
||||||
Attachment details = client.getAttachment(serverId, att.getId());
|
VolumeAttachment testAttachment = client.attachVolume(serverId, testVolume.getId(), "/dev/vdf");
|
||||||
|
assertNotNull(testAttachment.getId());
|
||||||
|
assertEquals(testAttachment.getVolumeId(), testVolume.getId());
|
||||||
|
|
||||||
|
assertTrue(new RetryablePredicate<VolumeClient>(new Predicate<VolumeClient>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(VolumeClient volumeClient) {
|
||||||
|
return client.listAttachments(serverId).size() == before+1;
|
||||||
|
}
|
||||||
|
}, 60 * 1000L).apply(client));
|
||||||
|
|
||||||
|
attachments = client.listAttachments(serverId);
|
||||||
|
assertNotNull(attachments);
|
||||||
|
assertEquals(attachments.size(), before+1);
|
||||||
|
|
||||||
|
assertEquals(client.getVolume(testVolume.getId()).getStatus(), Volume.Status.IN_USE);
|
||||||
|
|
||||||
|
boolean foundIt = false;
|
||||||
|
for (VolumeAttachment att : attachments) {
|
||||||
|
VolumeAttachment details = client.getAttachment(serverId, att.getId());
|
||||||
assertNotNull(details);
|
assertNotNull(details);
|
||||||
assertNotNull(details.getId());
|
assertNotNull(details.getId());
|
||||||
assertNotNull(details.getServerId());
|
assertNotNull(details.getServerId());
|
||||||
assertNotNull(details.getVolumeId());
|
assertNotNull(details.getVolumeId());
|
||||||
|
if (Objects.equal(details.getVolumeId(), testVolume.getId())) {
|
||||||
|
foundIt = true;
|
||||||
|
assertEquals(details.getDevice(), "/dev/vdf");
|
||||||
|
assertEquals(details.getServerId(), serverId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertTrue(foundIt, "Failed to find the attachment we created in listAttachments() response");
|
||||||
|
|
||||||
|
client.detachVolume(serverId, testVolume.getId());
|
||||||
|
assertTrue(new RetryablePredicate<VolumeClient>(new Predicate<VolumeClient>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(VolumeClient volumeClient) {
|
||||||
|
return client.listAttachments(serverId).size() == before;
|
||||||
|
}
|
||||||
|
}, 60 * 1000L).apply(client));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue