Merge pull request #153 from vijaykiran/volume-client

Volume client
This commit is contained in:
Adrian Cole 2011-11-15 04:23:37 -08:00
commit 6b834c9d44
10 changed files with 1346 additions and 0 deletions

View File

@ -34,9 +34,11 @@ import org.jclouds.cloudstack.features.NetworkAsyncClient;
import org.jclouds.cloudstack.features.OfferingAsyncClient;
import org.jclouds.cloudstack.features.SSHKeyPairAsyncClient;
import org.jclouds.cloudstack.features.SecurityGroupAsyncClient;
import org.jclouds.cloudstack.features.SnapshotAsyncClient;
import org.jclouds.cloudstack.features.TemplateAsyncClient;
import org.jclouds.cloudstack.features.VMGroupAsyncClient;
import org.jclouds.cloudstack.features.VirtualMachineAsyncClient;
import org.jclouds.cloudstack.features.VolumeAsyncClient;
import org.jclouds.cloudstack.features.ZoneAsyncClient;
import org.jclouds.rest.annotations.Delegate;
@ -170,4 +172,16 @@ public interface CloudStackAsyncClient {
*/
@Delegate
ISOAsyncClient getISOClient();
/**
* Provides asynchronous access to Volumes
*/
@Delegate
VolumeAsyncClient getVolumeClient();
/**
* Provides asynchronous access to Snapshots
*/
@Delegate
SnapshotAsyncClient getSnapshotClient();
}

View File

@ -36,9 +36,11 @@ import org.jclouds.cloudstack.features.NetworkClient;
import org.jclouds.cloudstack.features.OfferingClient;
import org.jclouds.cloudstack.features.SSHKeyPairClient;
import org.jclouds.cloudstack.features.SecurityGroupClient;
import org.jclouds.cloudstack.features.SnapshotClient;
import org.jclouds.cloudstack.features.TemplateClient;
import org.jclouds.cloudstack.features.VMGroupClient;
import org.jclouds.cloudstack.features.VirtualMachineClient;
import org.jclouds.cloudstack.features.VolumeClient;
import org.jclouds.cloudstack.features.ZoneClient;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
@ -173,4 +175,16 @@ public interface CloudStackClient {
*/
@Delegate
ISOClient getISOClient();
/**
* Provides synchronous access to Volumes
*/
@Delegate
VolumeClient getVolumeClient();
/**
* Provides synchronous access to Snapshots
*/
@Delegate
SnapshotClient getSnapshotClient();
}

View File

@ -55,12 +55,16 @@ import org.jclouds.cloudstack.features.SSHKeyPairAsyncClient;
import org.jclouds.cloudstack.features.SSHKeyPairClient;
import org.jclouds.cloudstack.features.SecurityGroupAsyncClient;
import org.jclouds.cloudstack.features.SecurityGroupClient;
import org.jclouds.cloudstack.features.SnapshotAsyncClient;
import org.jclouds.cloudstack.features.SnapshotClient;
import org.jclouds.cloudstack.features.TemplateAsyncClient;
import org.jclouds.cloudstack.features.TemplateClient;
import org.jclouds.cloudstack.features.VMGroupAsyncClient;
import org.jclouds.cloudstack.features.VMGroupClient;
import org.jclouds.cloudstack.features.VirtualMachineAsyncClient;
import org.jclouds.cloudstack.features.VirtualMachineClient;
import org.jclouds.cloudstack.features.VolumeAsyncClient;
import org.jclouds.cloudstack.features.VolumeClient;
import org.jclouds.cloudstack.features.ZoneAsyncClient;
import org.jclouds.cloudstack.features.ZoneClient;
import org.jclouds.cloudstack.handlers.CloudStackErrorHandler;
@ -104,6 +108,8 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
.put(SSHKeyPairClient.class, SSHKeyPairAsyncClient.class)//
.put(VMGroupClient.class, VMGroupAsyncClient.class)//
.put(ISOClient.class, ISOAsyncClient.class)//
.put(VolumeClient.class, VolumeAsyncClient.class)//
.put(SnapshotClient.class, SnapshotAsyncClient.class)//
.build();
public CloudStackRestClientModule() {

View File

@ -0,0 +1,571 @@
/**
* 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.cloudstack.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.Map;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.gson.annotations.SerializedName;
/**
* @author Vijay Kiran
*/
public class Volume implements Comparable<Volume> {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private long id;
private Date attached;
private Date created;
private boolean destroyed;
private long deviceId;
private String diskOfferingDisplayText;
private long diskOfferingId;
private String diskOfferingName;
private String domain;
private long domainId;
private String hypervisor;
private boolean isExtractable;
private long jobId;
private String jobStatus;
private String name;
private String serviceOfferingDisplayText;
private long serviceOfferingId;
private String serviceOfferingName;
private long size;
private long snapshotId;
private String state;
private String storage;
private String storageType;
private VolumeType type;
private long virtualMachineId;
private String vmDisplayName;
private String vmName;
private VirtualMachine.State vmState;
private long zoneId;
private String zoneName;
public Builder id(long id) {
this.id = id;
return this;
}
public Builder attached(Date attached) {
this.attached = attached;
return this;
}
public Builder created(Date created) {
this.created = created;
return this;
}
public Builder destroyed(boolean destroyed) {
this.destroyed = destroyed;
return this;
}
public Builder deviceId(long deviceId) {
this.deviceId = deviceId;
return this;
}
public Builder diskOfferingDisplayText(String diskOfferingDisplayText) {
this.diskOfferingDisplayText = diskOfferingDisplayText;
return this;
}
public Builder diskOfferingId(long diskOfferingId) {
this.diskOfferingId = diskOfferingId;
return this;
}
public Builder diskOfferingName(String diskOfferingName) {
this.diskOfferingName = diskOfferingName;
return this;
}
public Builder domain(String domain) {
this.domain = domain;
return this;
}
public Builder domainId(long domainId) {
this.domainId = domainId;
return this;
}
public Builder hypervisor(String hypervisor) {
this.hypervisor = hypervisor;
return this;
}
public Builder isExtractable(boolean isExtractable) {
this.isExtractable = isExtractable;
return this;
}
public Builder jobId(long jobId) {
this.jobId = jobId;
return this;
}
public Builder jobStatus(String jobStatus) {
this.jobStatus = jobStatus;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder serviceOfferingDisplayText(String serviceOfferingDisplayText) {
this.serviceOfferingDisplayText = serviceOfferingDisplayText;
return this;
}
public Builder serviceOfferingId(long serviceOfferingId) {
this.serviceOfferingId = serviceOfferingId;
return this;
}
public Builder serviceOfferingName(String serviceOfferingName) {
this.serviceOfferingName = serviceOfferingName;
return this;
}
public Builder size(long size) {
this.size = size;
return this;
}
public Builder snapshotId(long snapshotId) {
this.snapshotId = snapshotId;
return this;
}
public Builder state(String state) {
this.state = state;
return this;
}
public Builder storage(String storage) {
this.storage = storage;
return this;
}
public Builder storageType(String storageType) {
this.storageType = storageType;
return this;
}
public Builder type(VolumeType type) {
this.type = type;
return this;
}
public Builder virtualMachineId(long virtualMachineId) {
this.virtualMachineId = virtualMachineId;
return this;
}
public Builder vmDisplayName(String vmDisplayName) {
this.vmDisplayName = vmDisplayName;
return this;
}
public Builder vmName(String vmName) {
this.vmName = vmName;
return this;
}
public Builder vmState(VirtualMachine.State vmState) {
this.vmState = vmState;
return this;
}
public Builder zoneId(long zoneId) {
this.zoneId = zoneId;
return this;
}
public Builder zoneName(String zoneName) {
this.zoneName = zoneName;
return this;
}
public Volume build() {
return new Volume(id, attached, created, destroyed, deviceId, diskOfferingDisplayText,
diskOfferingId, diskOfferingName, domain, domainId, hypervisor, isExtractable,
jobId, jobStatus, name, serviceOfferingDisplayText, serviceOfferingId,
serviceOfferingName, size, snapshotId, state, storage, storage, type, virtualMachineId,
vmDisplayName, vmName, vmState, zoneId, zoneName);
}
}
// for deserialization
Volume() {
}
private long id;
private Date attached;
private Date created;
private boolean destroyed;
@SerializedName("deviceid")
private long deviceId;
@SerializedName("diskofferingdisplaytext")
private String diskOfferingDisplayText;
@SerializedName("diskofferingid")
private long diskOfferingId;
@SerializedName("diskofferingname")
private String diskOfferingName;
private String domain;
@SerializedName("domainid")
private long domainId;
private String hypervisor;
@SerializedName("isextractable")
private boolean isExtractable;
@SerializedName("jobid")
private long jobId;
@SerializedName("jobstatus")
//TODO Change to enum
private String jobStatus;
private String name;
@SerializedName("serviceofferingdisplaytext")
private String serviceOfferingDisplayText;
@SerializedName("serviceofferingid")
private long serviceOfferingId;
@SerializedName("serviceofferingname")
private String serviceOfferingName;
private long size;
@SerializedName("snapshotid")
private long snapshotId;
private String state;
private String storage;
@SerializedName("storagetype")
private String storageType;
private VolumeType type;
@SerializedName("virtualmachineid")
private long virtualMachineId;
@SerializedName("vmdisplayname")
private String vmDisplayName;
@SerializedName("vmname")
private String vmName;
@SerializedName("vmstate")
private VirtualMachine.State vmState;
@SerializedName("zoneid")
private long zoneId;
@SerializedName("zonename")
private String zoneName;
public Volume(long id, Date attached, Date created, boolean destroyed, long deviceId,
String diskOfferingDisplayText, long diskOfferingId, String diskOfferingName,
String domain, long domainId, String hypervisor, boolean extractable, long jobId,
String jobStatus, String name, String serviceOfferingDisplayText, long serviceOfferingId,
String serviceOfferingName, long size, long snapshotId, String state, String storage,
String storageType, VolumeType type, long virtualMachineId, String vmDisplayName, String vmName,
VirtualMachine.State vmState, long zoneId, String zoneName) {
this.id = id;
this.attached = attached;
this.created = created;
this.destroyed = destroyed;
this.deviceId = deviceId;
this.diskOfferingDisplayText = diskOfferingDisplayText;
this.diskOfferingId = diskOfferingId;
this.diskOfferingName = diskOfferingName;
this.domain = domain;
this.domainId = domainId;
this.hypervisor = hypervisor;
isExtractable = extractable;
this.jobId = jobId;
this.jobStatus = jobStatus;
this.name = name;
this.serviceOfferingDisplayText = serviceOfferingDisplayText;
this.serviceOfferingId = serviceOfferingId;
this.serviceOfferingName = serviceOfferingName;
this.size = size;
this.snapshotId = snapshotId;
this.state = state;
this.storage = storage;
this.storageType = storageType;
this.type = type;
this.virtualMachineId = virtualMachineId;
this.vmDisplayName = vmDisplayName;
this.vmName = vmName;
this.vmState = vmState;
this.zoneId = zoneId;
this.zoneName = zoneName;
}
public long getId() {
return id;
}
public Date getAttached() {
return attached;
}
public Date getCreated() {
return created;
}
public boolean isDestroyed() {
return destroyed;
}
public long getDeviceId() {
return deviceId;
}
public String getDiskOfferingDisplayText() {
return diskOfferingDisplayText;
}
public long getDiskOfferingId() {
return diskOfferingId;
}
public String getDiskOfferingName() {
return diskOfferingName;
}
public String getDomain() {
return domain;
}
public long getDomainId() {
return domainId;
}
public String getHypervisor() {
return hypervisor;
}
public boolean isExtractable() {
return isExtractable;
}
public long getJobId() {
return jobId;
}
public String getJobStatus() {
return jobStatus;
}
public String getName() {
return name;
}
public String getServiceOfferingDisplayText() {
return serviceOfferingDisplayText;
}
public long getServiceOfferingId() {
return serviceOfferingId;
}
public String getServiceOfferingName() {
return serviceOfferingName;
}
public long getSize() {
return size;
}
public long getSnapshotId() {
return snapshotId;
}
public String getState() {
return state;
}
public String getStorage() {
return storage;
}
public String getStorageType() {
return storageType;
}
public VolumeType getType() {
return type;
}
public long getVirtualMachineId() {
return virtualMachineId;
}
public String getVmDisplayName() {
return vmDisplayName;
}
public String getVmName() {
return vmName;
}
public VirtualMachine.State getVmState() {
return vmState;
}
public long getZoneId() {
return zoneId;
}
public String getZoneName() {
return zoneName;
}
@Override
public int compareTo(Volume volume) {
return Long.valueOf(this.id).compareTo(volume.id);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Volume volume = (Volume) o;
if (deviceId != volume.deviceId) return false;
if (diskOfferingId != volume.diskOfferingId) return false;
if (domainId != volume.domainId) return false;
if (id != volume.id) return false;
if (isExtractable != volume.isExtractable) return false;
if (jobId != volume.jobId) return false;
if (serviceOfferingId != volume.serviceOfferingId) return false;
if (size != volume.size) return false;
if (snapshotId != volume.snapshotId) return false;
if (virtualMachineId != volume.virtualMachineId) return false;
if (zoneId != volume.zoneId) return false;
if (attached != null ? !attached.equals(volume.attached) : volume.attached != null) return false;
if (!created.equals(volume.created)) return false;
if (diskOfferingDisplayText != null ? !diskOfferingDisplayText.equals(volume.diskOfferingDisplayText) :
volume.diskOfferingDisplayText != null)
return false;
if (diskOfferingName != null ? !diskOfferingName.equals(volume.diskOfferingName) : volume.diskOfferingName != null)
return false;
if (!domain.equals(volume.domain)) return false;
if (hypervisor != null ? !hypervisor.equals(volume.hypervisor) : volume.hypervisor != null) return false;
if (jobStatus != null ? !jobStatus.equals(volume.jobStatus) : volume.jobStatus != null) return false;
if (name != null ? !name.equals(volume.name) : volume.name != null) return false;
if (serviceOfferingDisplayText != null ? !serviceOfferingDisplayText.equals(volume.serviceOfferingDisplayText) :
volume.serviceOfferingDisplayText != null)
return false;
if (serviceOfferingName != null ? !serviceOfferingName.equals(volume.serviceOfferingName) :
volume.serviceOfferingName != null)
return false;
if (state != null ? !state.equals(volume.state) : volume.state != null) return false;
if (storage != null ? !storage.equals(volume.storage) : volume.storage != null) return false;
if (storageType != null ? !storageType.equals(volume.storageType) : volume.storageType != null) return false;
if (type != null ? !type.equals(volume.type) : volume.type != null) return false;
if (vmDisplayName != null ? !vmDisplayName.equals(volume.vmDisplayName) : volume.vmDisplayName != null)
return false;
if (vmName != null ? !vmName.equals(volume.vmName) : volume.vmName != null) return false;
if (vmState != volume.vmState) return false;
if (zoneName != null ? !zoneName.equals(volume.zoneName) : volume.zoneName != null) return false;
return true;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (attached != null ? attached.hashCode() : 0);
result = 31 * result + created.hashCode();
result = 31 * result + (int) (deviceId ^ (deviceId >>> 32));
result = 31 * result + (diskOfferingDisplayText != null ? diskOfferingDisplayText.hashCode() : 0);
result = 31 * result + (int) (diskOfferingId ^ (diskOfferingId >>> 32));
result = 31 * result + (diskOfferingName != null ? diskOfferingName.hashCode() : 0);
result = 31 * result + domain.hashCode();
result = 31 * result + (int) (domainId ^ (domainId >>> 32));
result = 31 * result + (hypervisor != null ? hypervisor.hashCode() : 0);
result = 31 * result + (isExtractable ? 1 : 0);
result = 31 * result + (int) (jobId ^ (jobId >>> 32));
result = 31 * result + (jobStatus != null ? jobStatus.hashCode() : 0);
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (serviceOfferingDisplayText != null ? serviceOfferingDisplayText.hashCode() : 0);
result = 31 * result + (int) (serviceOfferingId ^ (serviceOfferingId >>> 32));
result = 31 * result + (serviceOfferingName != null ? serviceOfferingName.hashCode() : 0);
result = 31 * result + (int) (size ^ (size >>> 32));
result = 31 * result + (int) (snapshotId ^ (snapshotId >>> 32));
result = 31 * result + (state != null ? state.hashCode() : 0);
result = 31 * result + (storage != null ? storage.hashCode() : 0);
result = 31 * result + (storageType != null ? storageType.hashCode() : 0);
result = 31 * result + (type != null ? type.hashCode() : 0);
result = 31 * result + (int) (virtualMachineId ^ (virtualMachineId >>> 32));
result = 31 * result + (vmDisplayName != null ? vmDisplayName.hashCode() : 0);
result = 31 * result + (vmName != null ? vmName.hashCode() : 0);
result = 31 * result + (vmState != null ? vmState.hashCode() : 0);
result = 31 * result + (int) (zoneId ^ (zoneId >>> 32));
result = 31 * result + (zoneName != null ? zoneName.hashCode() : 0);
return result;
}
public enum VolumeType {
ROOT(0),
DATADISK(1),
UNRECOGNIZED(Integer.MAX_VALUE);
private int code;
private static final Map<Integer, VolumeType> INDEX = Maps.uniqueIndex(ImmutableSet.copyOf(VolumeType.values()),
new Function<VolumeType, Integer>() {
@Override
public Integer apply(VolumeType input) {
return input.code;
}
});
VolumeType(int code) {
this.code = code;
}
@Override
public String toString() {
return name();
}
public static VolumeType fromValue(String resourceType) {
Integer code = new Integer(checkNotNull(resourceType, "resourcetype"));
return INDEX.containsKey(code) ? INDEX.get(code) : UNRECOGNIZED;
}
}
}

View File

@ -0,0 +1,111 @@
/**
* 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.cloudstack.features;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.Set;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.Volume;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.ListVolumesOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
/**
* Provides asynchronous access to cloudstack via their REST API.
* <p/>
*
* @author Vijay Kiran
* @see org.jclouds.cloudstack.features.VolumeClient
* @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
*/
@RequestFilters(QuerySigner.class)
@QueryParams(keys = "response", values = "json")
public interface VolumeAsyncClient {
/**
* @see VolumeClient#listVolumes(org.jclouds.cloudstack.options.ListVolumesOptions...)
*/
@GET
@QueryParams(keys = "command", values = "listVolumes")
@SelectJson("volume")
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Volume>> listVolumes(ListVolumesOptions... options);
/**
* @see VolumeClient#createVolumeFromDiskOfferingInZone(String, long, long)
*/
@GET
@QueryParams(keys = "command", values = "createVolume")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<AsyncCreateResponse> createVolumeFromDiskOfferingInZone(@QueryParam("name") String name,
@QueryParam("diskofferingid") long diskOfferingId,
@QueryParam("zoneid") long zoneId);
/**
* @see VolumeClient#createVolumeFromSnapshotInZone(String, long, long)
*/
@GET
@QueryParams(keys = "command", values = "createVolume")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<AsyncCreateResponse> createVolumeFromSnapshotInZone(@QueryParam("name") String name,
@QueryParam("snapshotid") long snapshotId,
@QueryParam("zoneid") long zoneId);
/**
* @see VolumeClient#attachVolume(long, long)
*/
@GET
@QueryParams(keys = "command", values = "attachVolume")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<AsyncCreateResponse> attachVolume(@QueryParam("id") long volumeId,
@QueryParam("virtualmachineid") long virtualMachineId);
/**
* @see VolumeClient#detachVolume(long)
*/
@GET
@QueryParams(keys = "command", values = "detachVolume")
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<AsyncCreateResponse> detachVolume(@QueryParam("id") long volumeId);
/**
* @see VolumeClient#deleteVolume(long)
*/
@GET
@QueryParams(keys = "command", values = "deleteVolume")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
ListenableFuture<Void> deleteVolume(@QueryParam("id") long id);
}

View File

@ -0,0 +1,90 @@
/**
* 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.cloudstack.features;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.Volume;
import org.jclouds.cloudstack.options.ListVolumesOptions;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to CloudStack Event features.
* <p/>
*
* @author Vijay Kiran
* @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface VolumeClient {
/**
* Create a volume with given name and diskOfferingId
*
* @param name name of the volume
* @param diskOfferingId the ID of the disk offering.
* @param zoneId the ID of the availability zone
* @return AsyncCreateResponse job response used to track creation
*/
AsyncCreateResponse createVolumeFromDiskOfferingInZone(String name, long diskOfferingId, long zoneId);
/**
* Create a volume with given name and snapshotId
*
* @param name name of the volume
* @param snapshotId Snapshot id to be used while creating the volume
* @param zoneId the ID of the availability zone
* @return AsyncCreateResponse job response used to track creation
*/
AsyncCreateResponse createVolumeFromSnapshotInZone(String name, long snapshotId, long zoneId);
/**
* List volumes
*
* @return volume list or null if not found
*/
Set<Volume> listVolumes(ListVolumesOptions... options);
/**
* Deletes a attached disk volume
*
* @param id id of the volume
*/
void deleteVolume(long id);
/**
* Attaches a disk volume to a virtual machine.
*
* @param volumeId the ID of the disk volume
* @param virtualMachineId the ID of the virtual machine
* @return AsyncCreateResponse job response used to track creation
*/
AsyncCreateResponse attachVolume(long volumeId, long virtualMachineId);
/**
* Detaches a disk volume to a virtual machine.
*
* @param volumeId the ID of the disk volume
* @return AsyncCreateResponse job response used to track creation
*/
AsyncCreateResponse detachVolume(long volumeId);
}

View File

@ -0,0 +1,218 @@
/**
* 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.cloudstack.options;
import com.google.common.collect.ImmutableSet;
/**
* Options used to control what volume
*
* @author Vijay Kiran
*/
public class ListVolumesOptions extends AccountInDomainOptions {
public static final ListVolumesOptions NONE = new ListVolumesOptions();
/**
* List volumes on specified host
*
* @param hostId hostId.
*/
public ListVolumesOptions hostId(long hostId) {
this.queryParameters.replaceValues("hostid", ImmutableSet.of(hostId + ""));
return this;
}
/**
* @param id the ID of the volume
*/
public ListVolumesOptions id(long id) {
this.queryParameters.replaceValues("id", ImmutableSet.of(id + ""));
return this;
}
/**
* @param recursive defaults to false, but if true, lists all volumes from the parent specified by the domain id till leaves.
*/
public ListVolumesOptions isRecursive(boolean recursive) {
this.queryParameters.replaceValues("isrecursive", ImmutableSet.of(String.valueOf(recursive)));
return this;
}
/**
* @param keyword List by keyword
*/
public ListVolumesOptions keyword(String keyword) {
this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword));
return this;
}
/**
* @param name the name of the disk volume
*/
public ListVolumesOptions name(String name) {
this.queryParameters.replaceValues("name", ImmutableSet.of(name));
return this;
}
/**
* @param podId the pod id the disk volume belongs to
*/
public ListVolumesOptions podId(long podId) {
this.queryParameters.replaceValues("podid", ImmutableSet.of(podId + ""));
return this;
}
/**
* @param type the type of the disk volume
*/
public ListVolumesOptions type(String type) {
this.queryParameters.replaceValues("type", ImmutableSet.of(type + ""));
return this;
}
/**
* @param virtualMachineId list volumes by id virtual machine.
*/
public ListVolumesOptions virtualMachineId(long virtualMachineId) {
this.queryParameters.replaceValues("virtualmachineid", ImmutableSet.of(virtualMachineId + ""));
return this;
}
/**
* @param zoneId list volumes by zoneId.
*/
public ListVolumesOptions zoneId(long zoneId) {
this.queryParameters.replaceValues("zoneid", ImmutableSet.of(zoneId + ""));
return this;
}
public static class Builder {
/**
* @see ListVolumesOptions#accountInDomain
*/
public static ListVolumesOptions accountInDomain(String account, long domain) {
ListVolumesOptions options = new ListVolumesOptions();
return options.accountInDomain(account, domain);
}
/**
* @see ListVolumesOptions#domainId
*/
public static ListVolumesOptions domainId(long id) {
ListVolumesOptions options = new ListVolumesOptions();
return options.domainId(id);
}
/**
* @see ListVolumesOptions#hostId
*/
public static ListVolumesOptions hostId(long id) {
ListVolumesOptions options = new ListVolumesOptions();
return options.hostId(id);
}
/**
* @see ListVolumesOptions#id
*/
public static ListVolumesOptions id(long id) {
ListVolumesOptions options = new ListVolumesOptions();
return options.id(id);
}
/**
* @see ListVolumesOptions#isRecursive(boolean)
*/
public static ListVolumesOptions isRecursive(boolean recursive) {
ListVolumesOptions options = new ListVolumesOptions();
return isRecursive(recursive);
}
/**
* @see ListVolumesOptions#name
*/
public static ListVolumesOptions keyword(String keyword) {
ListVolumesOptions options = new ListVolumesOptions();
return options.keyword(keyword);
}
/**
* @see ListVolumesOptions#name
*/
public static ListVolumesOptions name(String name) {
ListVolumesOptions options = new ListVolumesOptions();
return options.name(name);
}
/**
* @see ListVolumesOptions#podId
*/
public static ListVolumesOptions podId(long id) {
ListVolumesOptions options = new ListVolumesOptions();
return options.podId(id);
}
/**
* @see ListVolumesOptions#type
*/
public static ListVolumesOptions type(String type) {
ListVolumesOptions options = new ListVolumesOptions();
return options.type(type);
}
/**
* @see ListVolumesOptions#virtualMachineId(long)
*/
public static ListVolumesOptions virtualMachineId(long virtualMachineId) {
ListVolumesOptions options = new ListVolumesOptions();
return options.virtualMachineId(virtualMachineId);
}
/**
* @see ListVolumesOptions#zoneId
*/
public static ListVolumesOptions zoneId(long id) {
ListVolumesOptions options = new ListVolumesOptions();
return options.zoneId(id);
}
}
/**
* {@inheritDoc}
*/
@Override
public ListVolumesOptions accountInDomain(String account, long domain) {
return ListVolumesOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListVolumesOptions domainId(long domainId) {
return ListVolumesOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -62,6 +62,8 @@ public class CloudStackAsyncClientTest extends BaseCloudStackAsyncClientTest<Clo
assert syncClient.getEventClient() != null;
assert syncClient.getLimitClient() != null;
assert syncClient.getISOClient() != null;
assert syncClient.getVolumeClient() != null;
assert syncClient.getSnapshotClient() != null;
}
public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
@ -85,6 +87,8 @@ public class CloudStackAsyncClientTest extends BaseCloudStackAsyncClientTest<Clo
assert asyncClient.getEventClient() != null;
assert asyncClient.getLimitClient() != null;
assert asyncClient.getISOClient() != null;
assert asyncClient.getVolumeClient() != null;
assert asyncClient.getSnapshotClient() != null;
}

View File

@ -0,0 +1,145 @@
/**
* 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.cloudstack.features;
import java.io.IOException;
import java.lang.reflect.Method;
import com.google.inject.TypeLiteral;
import org.jclouds.cloudstack.options.ListVolumesOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code EventAsyncClient}
*
* @author Vijay Kiran
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during
// surefire
@Test(groups = "unit", testName = "VolumeAsyncClientTest")
public class VolumeAsyncClientTest extends BaseCloudStackAsyncClientTest<VolumeAsyncClient> {
protected String prefix = System.getProperty("user.name");
public void testListVolumes() throws SecurityException, NoSuchMethodException, IOException {
Method method = VolumeAsyncClient.class.getMethod("listVolumes", ListVolumesOptions[].class);
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listVolumes HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testCreateVolumeWithSnapshot() throws SecurityException, NoSuchMethodException, IOException {
Method method = VolumeAsyncClient.class.getMethod("createVolumeWithSnapshot", String.class, long.class);
HttpRequest httpRequest = processor.createRequest(method, prefix + "-jclouds-volume", 999L);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=createVolume&name="
+ prefix + "-jclouds-volume&snapshotid=999 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertSaxResponseParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testCreateVolumeFromDiskOffering() throws SecurityException, NoSuchMethodException, IOException {
Method method = VolumeAsyncClient.class.getMethod("createVolumeFromDiskOfferingInZone",
String.class, long.class, long.class);
HttpRequest httpRequest = processor.createRequest(method, prefix + "-jclouds-volume", 999L, 111L);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=createVolume&name="
+ prefix + "-jclouds-volume&zoneid=111&diskofferingid=999 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertSaxResponseParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testAttachVolume() throws SecurityException, NoSuchMethodException, IOException {
Method method = VolumeAsyncClient.class.getMethod("attachVolume",
long.class, long.class);
HttpRequest httpRequest = processor.createRequest(method, 111L, 999L);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=attachVolume&id=111&virtualmachineid=999 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertSaxResponseParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
Method method = VolumeAsyncClient.class.getMethod("detachVolume", long.class);
HttpRequest httpRequest = processor.createRequest(method, 111L);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=detachVolume&id=111 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertSaxResponseParserClassEquals(method, null);
checkFilters(httpRequest);
}
public void testDeleteVolume() throws SecurityException, NoSuchMethodException, IOException {
Method method = VolumeAsyncClient.class.getMethod("deleteVolume", long.class);
HttpRequest httpRequest = processor.createRequest(method, prefix + "-jclouds-volume");
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=deleteVolume&id="
+ prefix + "-jclouds-volume HTTP/1.1");
assertPayloadEquals(httpRequest, null, null, false);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<VolumeAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<VolumeAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,173 @@
/**
* 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.cloudstack.features;
import static com.google.common.collect.Iterables.find;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNotSame;
import java.util.Set;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.Volume;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code SSHKeyPairClient}
*
* @author Vijay Kiran
*/
@Test(groups = "live", singleThreaded = true, testName = "VolumeClientLiveTest")
public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest {
protected String prefix = System.getProperty("user.name");
private long zoneId;
private long diskOfferingId;
private long snapshotId;
private Volume volume;
public void testListVolumes() {
final Set<Volume> volumes = client.getVolumeClient().listVolumes();
for (Volume volume : volumes) {
checkVolume(volume);
}
}
public void testCreateVolumeFromDiskofferingInZoneAndDeleteVolume() {
zoneId = Iterables.getFirst(client.getZoneClient().listZones(), null).getId();
//Pick some disk offering
diskOfferingId = Iterables.getFirst(client.getOfferingClient().listDiskOfferings(), null).getId();
while (volume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().createVolumeFromDiskOfferingInZone(prefix + "-jclouds-volume",
diskOfferingId, zoneId);
assert jobComplete.apply(job.getJobId());
volume = findVolumeWithId(job.getId());
} catch (IllegalStateException e) {
//TODO volume creation failed - retry?
}
}
checkVolume(volume);
//Delete the volume
client.getVolumeClient().deleteVolume(volume.getId());
}
public void testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete() {
zoneId = Iterables.getFirst(client.getZoneClient().listZones(), null).getId();
//Pick some disk offering
diskOfferingId = Iterables.getFirst(client.getOfferingClient().listDiskOfferings(), null).getId();
while (volume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().createVolumeFromDiskOfferingInZone(prefix + "-jclouds-volume",
diskOfferingId, zoneId);
assert jobComplete.apply(job.getJobId());
volume = findVolumeWithId(job.getId());
} catch (IllegalStateException e) {
//TODO volume creation failed - retry?
}
}
checkVolume(volume);
long virtualMachineId = Iterables.getFirst(client.getVirtualMachineClient().listVirtualMachines(), null).getId();
//Attach Volume
Volume attachedVolume = null;
while (attachedVolume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().attachVolume(volume.getId(), virtualMachineId);
assert jobComplete.apply(job.getJobId());
attachedVolume = findVolumeWithId(volume.getId());
assert attachedVolume.getVirtualMachineId() == virtualMachineId;
assert attachedVolume.getAttached() != null;
} catch (IllegalStateException e) {
//TODO volume creation failed - retry?
}
}
//Detach Volume
Volume detachedVolume = null;
while (detachedVolume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().detachVolume(volume.getId());
assert jobComplete.apply(job.getJobId());
detachedVolume = findVolumeWithId(volume.getId());
checkVolume(detachedVolume);
} catch (IllegalStateException e) {
//TODO volume creation failed - retry?
}
}
//Cleanup
client.getVolumeClient().deleteVolume(volume.getId());
}
/*
TODO Uncomment this test after SnapshotClient has test coverage.
public void testCreateVolumeFromSnapshotInZoneAndDeleteVolume() {
zoneId = Iterables.getFirst(client.getZoneClient().listZones(), null).getId();
final Set<Snapshot> snapshots = client.getSnapshotClient().listSnapshots();
assertNotNull(snapshots);
assertNotSame(0, snapshots.size() );
snapshotId = Iterables.getFirst(snapshots, null).getId();
while (volume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().createVolumeFromSnapshotInZone(prefix + "-jclouds-volume",
snapshotId, zoneId);
assert jobComplete.apply(job.getJobId());
volume = findVolumeWithId(job.getId());
} catch (IllegalStateException e) {
//TODO volume creation failed - retry?
}
}
checkVolume(volume);
//Delete the volume
client.getVolumeClient().deleteVolume(volume.getId());
}
*/
private void checkVolume(final Volume volume) {
assertNotNull(volume.getId());
assertNotNull(volume.getName());
assertNotSame(Volume.VolumeType.UNRECOGNIZED, volume.getType());
}
private Volume findVolumeWithId(final long id) {
return find(client.getVolumeClient().listVolumes(), new Predicate<Volume>() {
@Override
public boolean apply(Volume arg0) {
return arg0.getId() == id;
}
});
}
}