Merge pull request #200 from ahgittin/cloudstack-templates

Cloudstack volumes and snapshots improvements
This commit is contained in:
Adrian Cole 2011-12-02 09:18:17 -08:00
commit dfd4861c3a
11 changed files with 525 additions and 276 deletions

View File

@ -48,6 +48,18 @@ public class BindTemplateMetadataToQueryParams implements Binder {
request = ModifyRequest.addQueryParam(request, "name", metadata.getName(), uriBuilderProvider.get());
request = ModifyRequest.addQueryParam(request, "ostypeid", metadata.getOsTypeId(), uriBuilderProvider.get());
request = ModifyRequest.addQueryParam(request, "displaytext", metadata.getDisplayText(), uriBuilderProvider.get());
if (metadata.getSnapshotId() != null) {
request = ModifyRequest.addQueryParam(request, "snapshotid", metadata.getSnapshotId(), uriBuilderProvider.get());
}
if (metadata.getVolumeId() != null) {
request = ModifyRequest.addQueryParam(request, "volumeid", metadata.getVolumeId(), uriBuilderProvider.get());
}
if (metadata.getVirtualMachineId() != null) {
request = ModifyRequest.addQueryParam(request, "virtualmachineid", metadata.getVirtualMachineId(), uriBuilderProvider.get());
}
if (metadata.getPasswordEnabled() != null) {
request = ModifyRequest.addQueryParam(request, "passwordenabled", metadata.getPasswordEnabled(), uriBuilderProvider.get());
}
return request;
}
}

View File

@ -18,11 +18,13 @@
*/
package org.jclouds.cloudstack.domain;
import com.google.gson.annotations.SerializedName;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.CaseFormat;
import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
/**
* @author Richard Downer
@ -48,7 +50,7 @@ public class Snapshot implements Comparable<Snapshot> {
private State state;
private long volumeId;
private String volumeName;
private String volumeType;
private Volume.VolumeType volumeType;
/**
* @param id ID of the snapshot
@ -157,27 +159,37 @@ public class Snapshot implements Comparable<Snapshot> {
/**
* @param volumeType type of the disk volume
*/
public Builder volumeType(String volumeType) {
public Builder volumeType(Volume.VolumeType volumeType) {
this.volumeType = volumeType;
return this;
}
public Snapshot build() {
return new Snapshot(id, account, created, domain, domainId, interval, jobId,
jobStatus, name, snapshotType, state, volumeId, volumeName, volumeType);
}
}
public static enum State {
public enum State {
BackedUp, Creating, BackingUp, UNRECOGNIZED;
BACKED_UP, CREATING, BACKING_UP, UNRECOGNIZED;
public static State fromValue(String type) {
@Override
public String toString() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
}
public static State fromValue(String state) {
try {
return valueOf(checkNotNull(type, "type"));
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static enum Type {
public enum Type {
MANUAL, RECURRING, UNRECOGNIZED;
@ -190,7 +202,7 @@ public class Snapshot implements Comparable<Snapshot> {
}
}
public static enum Interval {
public enum Interval {
HOURLY, DAILY, WEEKLY, MONTHLY, template, none, UNRECOGNIZED;
@ -224,7 +236,25 @@ public class Snapshot implements Comparable<Snapshot> {
@SerializedName("volumename")
private String volumeName;
@SerializedName("volumetype")
private String volumeType; // FIXME: replace this with a proper enumerated type (blocked until volume API implemented)
private Volume.VolumeType volumeType;
public Snapshot(long id, String account, Date created, String domain, long domainId, Interval interval, long jobId,
String jobStatus, String name, Type snapshotType, State state, long volumeId, String volumeName, Volume.VolumeType volumeType) {
this.id = id;
this.account = account;
this.created = created;
this.domain = domain;
this.domainId = domainId;
this.interval = interval;
this.jobId = jobId;
this.jobStatus = jobStatus;
this.name = name;
this.snapshotType = snapshotType;
this.state = state;
this.volumeId = volumeId;
this.volumeName = volumeName;
this.volumeType = volumeType;
}
/**
* present only for serializer
@ -326,7 +356,7 @@ public class Snapshot implements Comparable<Snapshot> {
/**
* @return type of the disk volume
*/
public String getVolumeType() {
public Volume.VolumeType getVolumeType() {
return volumeType;
}
@ -335,22 +365,22 @@ public class Snapshot implements Comparable<Snapshot> {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Snapshot snapshot = (Snapshot) o;
Snapshot that = (Snapshot) o;
if (domainId != snapshot.domainId) return false;
if (id != snapshot.id) return false;
if (jobId != snapshot.jobId) return false;
if (volumeId != snapshot.volumeId) return false;
if (account != null ? !account.equals(snapshot.account) : snapshot.account != null) return false;
if (created != null ? !created.equals(snapshot.created) : snapshot.created != null) return false;
if (domain != null ? !domain.equals(snapshot.domain) : snapshot.domain != null) return false;
if (interval != snapshot.interval) return false;
if (jobStatus != null ? !jobStatus.equals(snapshot.jobStatus) : snapshot.jobStatus != null) return false;
if (name != null ? !name.equals(snapshot.name) : snapshot.name != null) return false;
if (snapshotType != snapshot.snapshotType) return false;
if (state != snapshot.state) return false;
if (volumeName != null ? !volumeName.equals(snapshot.volumeName) : snapshot.volumeName != null) return false;
if (volumeType != null ? !volumeType.equals(snapshot.volumeType) : snapshot.volumeType != null) return false;
if (!Objects.equal(domainId, that.domainId)) return false;
if (!Objects.equal(id, that.id)) return false;
if (!Objects.equal(jobId, that.jobId)) return false;
if (!Objects.equal(volumeId, that.volumeId)) return false;
if (!Objects.equal(account, that.account)) return false;
if (!Objects.equal(created, that.created)) return false;
if (!Objects.equal(domain, that.domain)) return false;
if (!Objects.equal(interval, that.interval)) return false;
if (!Objects.equal(jobStatus, that.jobStatus)) return false;
if (!Objects.equal(name, that.name)) return false;
if (!Objects.equal(snapshotType, that.snapshotType)) return false;
if (!Objects.equal(state, that.state)) return false;
if (!Objects.equal(volumeName, that.volumeName)) return false;
if (!Objects.equal(volumeType, that.volumeType)) return false;
return true;
}
@ -377,21 +407,21 @@ public class Snapshot implements Comparable<Snapshot> {
@Override
public String toString() {
return "Snapshot[" +
"id=" + id +
", account='" + account + '\'' +
", created=" + created +
", domain='" + domain + '\'' +
", domainId=" + domainId +
", interval=" + interval +
", jobId=" + jobId +
", jobStatus='" + jobStatus + '\'' +
", name='" + name + '\'' +
", snapshotType=" + snapshotType +
", state=" + state +
", volumeId=" + volumeId +
", volumeName='" + volumeName + '\'' +
", volumeType='" + volumeType + '\'' +
']';
"id=" + id +
", account='" + account + '\'' +
", created=" + created +
", domain='" + domain + '\'' +
", domainId=" + domainId +
", interval=" + interval +
", jobId=" + jobId +
", jobStatus='" + jobStatus + '\'' +
", name='" + name + '\'' +
", snapshotType=" + snapshotType +
", state=" + state +
", volumeId=" + volumeId +
", volumeName='" + volumeName + '\'' +
", volumeType='" + volumeType + '\'' +
']';
}
@Override

View File

@ -86,6 +86,9 @@ public class SnapshotPolicy implements Comparable<SnapshotPolicy> {
return this;
}
public SnapshotPolicy build() {
return new SnapshotPolicy(id, interval, numberToRetain, schedule, timezone, volumeId);
}
}
private long id;
@ -98,6 +101,15 @@ public class SnapshotPolicy implements Comparable<SnapshotPolicy> {
@SerializedName("volumeid")
private long volumeId;
public SnapshotPolicy(long id, Snapshot.Interval interval, long numberToRetain, String schedule, String timezone, long volumeId) {
this.id = id;
this.interval = interval;
this.numberToRetain = numberToRetain;
this.schedule = schedule;
this.timezone = timezone;
this.volumeId = volumeId;
}
/**
* present only for serializer
*/

View File

@ -211,6 +211,7 @@ public class Template implements Comparable<Template> {
USER, BUILTIN, UNRECOGNIZED;
//TODO do we need camel case routines (e.g. see enums in VirtualMachine) ?
public static Type fromValue(String type) {
try {
return valueOf(checkNotNull(type, "type"));

View File

@ -18,116 +18,211 @@
*/
package org.jclouds.cloudstack.domain;
import com.google.common.base.Objects;
/**
* @author Richard Downer
*/
public class TemplateMetadata {
public static Builder builder() {
return new Builder();
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
public static class Builder {
private String name;
private long osTypeId;
private String displayText;
private Long snapshotId;
private Long volumeId;
private Long virtualMachineId;
private Boolean passwordEnabled;
private String name;
private long osTypeId;
private String displayText;
/**
* @param name
* the name of the template
*/
public Builder name(String name) {
this.name = name;
return this;
}
/**
* @param name the name of the template
*/
public Builder name(String name) {
this.name = name;
return this;
}
/**
* @param osTypeId
* the ID of the OS Type that best represents the OS of this template.
*/
public Builder osTypeId(long osTypeId) {
this.osTypeId = osTypeId;
return this;
}
/**
* @param osTypeId the ID of the OS Type that best represents the OS of this template.
*/
public Builder osTypeId(long osTypeId) {
this.osTypeId = osTypeId;
return this;
}
/**
* @param displayText
* the display text of the template. This is usually used for display purposes.
*/
public Builder displayText(String displayText) {
this.displayText = displayText;
return this;
}
/**
* @param displayText the display text of the template. This is usually used for display purposes.
*/
public Builder displayText(String displayText) {
this.displayText = displayText;
return this;
}
/**
* @param snapshotId
* the ID of the snapshot the template is being created from.
* Either this parameter, or volumeId has to be passed in
*/
public Builder snapshotId(Long snapshotId) {
this.snapshotId = snapshotId;
return this;
}
public TemplateMetadata build() {
return new TemplateMetadata(name, osTypeId, displayText);
}
}
/**
* @param volumeId
* the ID of the disk volume the template is being created from.
* Either this parameter, or snapshotId has to be passed in
*/
public Builder volumeId(Long volumeId) {
this.volumeId = volumeId;
return this;
}
private String name;
private long osTypeId;
private String displayText;
/**
* @param virtualMachineId
* the ID of the disk volume the template is being created from
*/
public Builder virtualMachineId(Long virtualMachineId) {
this.virtualMachineId = virtualMachineId;
return this;
}
public TemplateMetadata(String name, long osTypeId, String displayText) {
this.name = name;
this.osTypeId = osTypeId;
this.displayText = displayText;
}
/**
* the template supports the password reset feature.
*/
public Builder passwordEnabled() {
this.passwordEnabled = true;
return this;
}
/**
* present only for serializer
*/
TemplateMetadata() {
}
public TemplateMetadata build() {
TemplateMetadata template = new TemplateMetadata(name, osTypeId, displayText);
template.setPasswordEnabled(passwordEnabled);
template.setSnapshotId(snapshotId);
template.setVirtualMachineId(virtualMachineId);
template.setVolumeId(volumeId);
return template;
}
}
/**
* @return the name of the template
*/
public String getName() {
return name;
}
private String name;
private long osTypeId;
private String displayText;
/**
* @return the ID of the OS Type that best represents the OS of this template.
*/
public long getOsTypeId() {
return osTypeId;
}
private Long snapshotId;
private Long volumeId;
private Long virtualMachineId;;
private Boolean passwordEnabled;
/**
* @return the display text of the template. This is usually used for display purposes.
*/
public String getDisplayText() {
return displayText;
}
public TemplateMetadata(String name, long osTypeId, String displayText) {
this.name = name;
this.osTypeId = osTypeId;
this.displayText = displayText;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
/**
* present only for serializer
*/
TemplateMetadata() {
}
TemplateMetadata that = (TemplateMetadata) o;
/**
* @return the ID of the snapshot the template is being created from
*/
public Long getSnapshotId() {
return snapshotId;
}
if (osTypeId != that.osTypeId) return false;
if (displayText != null ? !displayText.equals(that.displayText) : that.displayText != null) return false;
if (name != null ? !name.equals(that.name) : that.name != null) return false;
public void setSnapshotId(Long snapshotId) {
this.snapshotId = snapshotId;
}
return true;
}
/**
* @return the ID of the disk volume the template is being created from
*/
public Long getVolumeId() {
return volumeId;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (int) (osTypeId ^ (osTypeId >>> 32));
result = 31 * result + (displayText != null ? displayText.hashCode() : 0);
return result;
}
public void setVolumeId(Long volumeId) {
this.volumeId = volumeId;
}
@Override
public String toString() {
return "[" +
"name='" + name + '\'' +
", osTypeId=" + osTypeId +
", displayText='" + displayText + '\'' +
']';
}
/**
* @return Optional, VM ID
*/
public Long getVirtualMachineId() {
return virtualMachineId;
}
public void setVirtualMachineId(Long virtualMachineId) {
this.virtualMachineId = virtualMachineId;
}
/**
* @return true if the template supports the password reset feature; default is false
*/
public Boolean getPasswordEnabled() {
return passwordEnabled;
}
public void setPasswordEnabled(Boolean passwordEnabled) {
this.passwordEnabled = passwordEnabled;
}
/**
* @return the name of the template
*/
public String getName() {
return name;
}
/**
* @return the ID of the OS Type that best represents the OS of this template.
*/
public long getOsTypeId() {
return osTypeId;
}
/**
* @return the display text of the template. This is usually used for display purposes.
*/
public String getDisplayText() {
return displayText;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TemplateMetadata that = (TemplateMetadata) o;
if (!Objects.equal(osTypeId, that.osTypeId)) return false;
if (!Objects.equal(snapshotId, that.snapshotId)) return false;
if (!Objects.equal(volumeId, that.volumeId)) return false;
if (!Objects.equal(virtualMachineId, that.virtualMachineId)) return false;
if (!Objects.equal(passwordEnabled, that.passwordEnabled)) return false;
if (!Objects.equal(displayText, that.displayText)) return false;
if (!Objects.equal(name, that.name)) return false;
return true;
}
@Override
public int hashCode() {
return Objects.hashCode(name, displayText, osTypeId, snapshotId, volumeId, passwordEnabled, virtualMachineId);
}
@Override
public String toString() {
return "[" + "name='" + name + '\'' + ", osTypeId=" + osTypeId + ", displayText='" + displayText + '\'' + ']';
}
}

View File

@ -955,18 +955,23 @@ public class VirtualMachine implements Comparable<VirtualMachine> {
@Override
public String toString() {
return "[id=" + id + ", account=" + account + ", cpuCount=" + cpuCount + ", cpuSpeed=" + cpuSpeed + ", cpuUsed="
+ cpuUsed + ", displayName=" + displayName + ", created=" + created + ", domain=" + domain + ", domainId="
+ domainId + ", usesVirtualNetwork=" + usesVirtualNetwork + ", group=" + group + ", groupId=" + groupId
+ ", guestOSId=" + guestOSId + ", HAEnabled=" + HAEnabled + ", hostId=" + hostId + ", hostname=" + hostname
+ ", IPAddress=" + IPAddress + ", ISODisplayText=" + ISODisplayText + ", ISOId=" + ISOId + ", ISOName="
+ ISOName + ", jobId=" + jobId + ", jobStatus=" + jobStatus + ", memory=" + memory + ", name=" + name
+ ", networkKbsRead=" + networkKbsRead + ", networkKbsWrite=" + networkKbsWrite + ", password=" + password
+ ", passwordEnabled=" + passwordEnabled + ", rootDeviceId=" + rootDeviceId + ", rootDeviceType="
+ rootDeviceType + ", serviceOfferingId=" + serviceOfferingId + ", serviceOfferingName="
+ serviceOfferingName + ", state=" + state + ", templateDisplayText=" + templateDisplayText
+ ", templateId=" + templateId + ", templateName=" + templateName + ", zoneId=" + zoneId + ", zoneName="
+ zoneName + ", nics=" + nics + ", hypervisor=" + hypervisor + ", securityGroups=" + securityGroups + "]";
return "[id=" + id
// + ", account=" + account + ", cpuCount=" + cpuCount + ", cpuSpeed=" + cpuSpeed + ", cpuUsed=" + cpuUsed
+ ", displayName=" + displayName + ", created=" + created
// + ", domain=" + domain + ", domainId="
// + domainId + ", usesVirtualNetwork=" + usesVirtualNetwork + ", group=" + group + ", groupId=" + groupId
// + ", guestOSId=" + guestOSId + ", HAEnabled=" + HAEnabled + ", hostId=" + hostId + ", hostname=" + hostname
+ ", IPAddress=" + IPAddress
// + ", ISODisplayText=" + ISODisplayText + ", ISOId=" + ISOId + ", ISOName="
// + ISOName + ", jobId=" + jobId + ", jobStatus=" + jobStatus + ", memory=" + memory + ", name=" + name
// + ", networkKbsRead=" + networkKbsRead + ", networkKbsWrite=" + networkKbsWrite + ", password=" + password
// + ", passwordEnabled=" + passwordEnabled + ", rootDeviceId=" + rootDeviceId + ", rootDeviceType="
// + rootDeviceType + ", serviceOfferingId=" + serviceOfferingId + ", serviceOfferingName=" + serviceOfferingName
+ ", state=" + state
// + ", templateDisplayText=" + templateDisplayText
// + ", templateId=" + templateId + ", templateName=" + templateName + ", zoneId=" + zoneId + ", zoneName="
// + zoneName + ", nics=" + nics + ", hypervisor=" + hypervisor + ", securityGroups=" + securityGroups
+ "]";
}
@Override

View File

@ -24,6 +24,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.Map;
import org.jclouds.cloudstack.domain.VirtualMachine.State;
import com.google.common.base.CaseFormat;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
@ -61,9 +64,8 @@ public class Volume implements Comparable<Volume> {
private String serviceOfferingName;
private long size;
private long snapshotId;
private String state;
private State state;
private String storage;
// TODO enum
private String storageType;
private VolumeType type;
private long virtualMachineId;
@ -173,7 +175,7 @@ public class Volume implements Comparable<Volume> {
return this;
}
public Builder state(String state) {
public Builder state(State state) {
this.state = state;
return this;
}
@ -231,11 +233,6 @@ public class Volume implements Comparable<Volume> {
}
}
// for deserialization
Volume() {
}
private long id;
private Date attached;
private Date created;
@ -257,7 +254,6 @@ public class Volume implements Comparable<Volume> {
@SerializedName("jobid")
private long jobId;
@SerializedName("jobstatus")
//TODO Change to enum
private String jobStatus;
private String name;
@SerializedName("serviceofferingdisplaytext")
@ -269,9 +265,10 @@ public class Volume implements Comparable<Volume> {
private long size;
@SerializedName("snapshotid")
private long snapshotId;
private String state;
private State state;
private String storage;
@SerializedName("storagetype")
// MAYDO: this should perhaps be an enum; only value I have seen is "shared"
private String storageType;
private VolumeType type;
@SerializedName("virtualmachineid")
@ -291,7 +288,7 @@ public class Volume implements Comparable<Volume> {
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 serviceOfferingName, long size, long snapshotId, State state, String storage,
String storageType, VolumeType type, long virtualMachineId, String vmDisplayName, String vmName,
VirtualMachine.State vmState, long zoneId, String zoneName) {
this.id = id;
@ -326,6 +323,10 @@ public class Volume implements Comparable<Volume> {
this.zoneName = zoneName;
}
// for deserialization
Volume() {
}
public long getId() {
return id;
}
@ -334,7 +335,6 @@ public class Volume implements Comparable<Volume> {
return attached;
}
public Date getCreated() {
return created;
}
@ -407,7 +407,7 @@ public class Volume implements Comparable<Volume> {
return snapshotId;
}
public String getState() {
public State getState() {
return state;
}
@ -534,6 +534,40 @@ public class Volume implements Comparable<Volume> {
result = 31 * result + (zoneName != null ? zoneName.hashCode() : 0);
return result;
}
@Override
public String toString() {
return getClass().getCanonicalName()+"["+id+"; "+name+"; "+vmState+"]";
}
public enum State {
/** indicates that the volume record is created in the DB, but not on the backend */
ALLOCATED,
/** the volume is being created on the backend */
CREATING,
/** the volume is ready to be used */
READY,
/** the volume is destroyed (either as a result of deleteVolume command for DataDisk or as a part of destroyVm) */
DESTROYED,
/** the volume has failed somehow, e.g. during creation (in cloudstack development) */
FAILED,
UNRECOGNIZED;
@Override
public String toString() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
}
public static State fromValue(String state) {
try {
return valueOf(CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(state, "state")));
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public enum VolumeType {
ROOT(0),

View File

@ -49,6 +49,7 @@ import org.jclouds.cloudstack.predicates.VirtualMachineDestroyed;
import org.jclouds.cloudstack.predicates.VirtualMachineRunning;
import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult;
import org.jclouds.compute.BaseVersionedServiceLiveTest;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.domain.Credentials;
@ -130,6 +131,7 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
protected String prefix = System.getProperty("user.name");
protected CloudStackContext computeContext;
protected ComputeService computeClient;
protected RestContext<CloudStackClient, CloudStackAsyncClient> context;
protected CloudStackClient client;
protected CloudStackClient adminClient;
@ -173,8 +175,10 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
public void setupClient() {
setupCredentials();
computeContext = CloudStackContext.class.cast(new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), setupProperties()));
computeContext = CloudStackContext.class.cast(new ComputeServiceContextFactory(setupRestProperties()).
createContext(provider, ImmutableSet.<Module> of(
new Log4JLoggingModule(), new SshjSshClientModule()), setupProperties()));
computeClient = computeContext.getComputeService();
context = computeContext.getProviderSpecificContext();
client = context.getApi();
user = verifyCurrentUserIsOfType(context, Account.Type.USER);
@ -182,9 +186,9 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
domainAdminEnabled = setupAdminProperties() != null;
if (domainAdminEnabled) {
domainAdminComputeContext = CloudStackContext.class.cast(new ComputeServiceContextFactory().createContext(
provider, ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()),
setupAdminProperties()));
domainAdminComputeContext = CloudStackContext.class.cast(new ComputeServiceContextFactory(setupRestProperties()).
createContext(provider, ImmutableSet.<Module> of(
new Log4JLoggingModule(), new SshjSshClientModule()), setupAdminProperties()));
domainAdminContext = domainAdminComputeContext.getDomainContext();
domainAdminClient = domainAdminContext.getApi();
domainAdminUser = verifyCurrentUserIsOfType(domainAdminContext, Account.Type.DOMAIN_ADMIN);

View File

@ -28,9 +28,15 @@ import static org.testng.AssertJUnit.assertTrue;
import java.util.Set;
import javax.annotation.Resource;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.Snapshot;
import org.jclouds.cloudstack.domain.Volume;
import org.jclouds.cloudstack.options.ListSnapshotsOptions;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.PredicateCallable;
import org.jclouds.predicates.Retryables;
import org.testng.annotations.Test;
import com.google.common.base.Function;
@ -40,11 +46,13 @@ import com.google.common.collect.Iterables;
/**
* Tests behavior of {@code SnapshotClient}
*
* @author grkvlt@apache.org
* @author grkvlt@apache.org, Alex Heneveld
*/
@Test(groups = "live", singleThreaded = true, testName = "SnapshotClientLiveTest")
public class SnapshotClientLiveTest extends BaseCloudStackClientLiveTest {
@Resource Logger logger = Logger.NULL;
public void testListSnapshots() {
Set<Snapshot> snapshots = client.getSnapshotClient().listSnapshots();
assertNotNull(snapshots);
@ -102,24 +110,30 @@ public class SnapshotClientLiveTest extends BaseCloudStackClientLiveTest {
assertNull(found);
}
public void testCreateSnapshotFromVolume() {
// Pick some volume
long volumeId = Iterables.get(client.getVolumeClient().listVolumes(), 0).getId();
Snapshot snapshot = null;
while (snapshot == null) {
try {
AsyncCreateResponse job = client.getSnapshotClient().createSnapshot(volumeId);
assertTrue(jobComplete.apply(job.getJobId()));
snapshot = findSnapshotWithId(job.getId());
} catch (IllegalStateException e) {
// TODO snapshot creation failed - retry?
}
protected Volume getPreferredVolume() {
for (Volume candidate : client.getVolumeClient().listVolumes()) {
if (candidate.getState() == Volume.State.READY)
return candidate;
}
throw new AssertionError("No suitable Volume found.");
}
public void testCreateSnapshotFromVolume() {
final Volume volume = getPreferredVolume(); //fail fast if none
Snapshot snapshot = Retryables.retryGettingResultOrFailing(new PredicateCallable<Snapshot>() {
public Snapshot call() {
logger.info("creating snapshot from volume %s", volume);
AsyncCreateResponse job = client.getSnapshotClient().createSnapshot(volume.getId());
assertTrue(jobComplete.apply(job.getJobId()));
return findSnapshotWithId(job.getId());
}
protected void onFailure() {
logger.info("failed creating snapshot (retrying): %s", getLastFailure());
}
}, null, 60*1000, "failed to create snapshot");
logger.info("created snapshot %s from volume %s", snapshot, volume);
checkSnapshot(snapshot);
// Delete the snapshot
client.getSnapshotClient().deleteSnapshot(snapshot.getId());
}

View File

@ -37,7 +37,7 @@ import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.zoneId
import static org.testng.Assert.*;
/**
* Tests behavior of {@code TemplateClientLiveTest}
* Tests behavior of {@code TemplateClient}
*
* @author Adrian Cole
*/

View File

@ -18,31 +18,46 @@
*/
package org.jclouds.cloudstack.features;
import static com.google.common.collect.Iterables.*;
import static org.testng.AssertJUnit.*;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNotSame;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import java.util.NoSuchElementException;
import java.util.Set;
import com.google.common.base.Function;
import javax.annotation.Resource;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.DiskOffering;
import org.jclouds.cloudstack.domain.Snapshot;
import org.jclouds.cloudstack.domain.VirtualMachine;
import org.jclouds.cloudstack.domain.Volume;
import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.options.ListVolumesOptions;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.PredicateCallable;
import org.jclouds.predicates.Retryables;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
* Tests behavior of {@code VolumeClient}
*
* @author Vijay Kiran
* @author Vijay Kiran, Alex Heneveld
*/
@Test(groups = "live", singleThreaded = true, testName = "VolumeClientLiveTest")
public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest {
protected String prefix = System.getProperty("user.name");
@Resource Logger logger = Logger.NULL;
protected String prefix = System.getProperty("user.name")+"-"+getClass().getSimpleName();
private long zoneId;
@ -66,10 +81,10 @@ public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest {
public void testListVolumesById() {
Iterable<Long> volumeIds = Iterables.transform(client.getVolumeClient().listVolumes(), new Function<Volume, Long>() {
public Long apply(Volume input) {
return input.getId();
}
});
public Long apply(Volume input) {
return input.getId();
}
});
assertNotNull(volumeIds);
assertFalse(Iterables.isEmpty(volumeIds));
@ -91,10 +106,10 @@ public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest {
public void testGetVolumeById() {
Iterable<Long> volumeIds = Iterables.transform(client.getVolumeClient().listVolumes(), new Function<Volume, Long>() {
public Long apply(Volume input) {
return input.getId();
}
});
public Long apply(Volume input) {
return input.getId();
}
});
assertNotNull(volumeIds);
assertFalse(Iterables.isEmpty(volumeIds));
@ -111,114 +126,141 @@ public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest {
assertNull(found);
}
public void testCreateVolumeFromDiskofferingInZoneAndDeleteVolume() {
// Pick some disk offering
long diskOfferingId = Iterables.get(client.getOfferingClient().listDiskOfferings(), 0).getId();
Volume volume = null;
while (volume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().createVolumeFromDiskOfferingInZone(prefix + "-jclouds-volume",
diskOfferingId, zoneId);
assertTrue(jobComplete.apply(job.getJobId()));
volume = findVolumeWithId(job.getId());
} catch (IllegalStateException e) {
// TODO volume creation failed - retry?
}
protected DiskOffering getPreferredDiskOffering() {
for (DiskOffering candidate : client.getOfferingClient().listDiskOfferings()) {
//any will do
return candidate;
}
throw new AssertionError("No suitable DiskOffering found.");
}
protected Snapshot getPreferredSnapshot() {
for (Snapshot candidate : client.getSnapshotClient().listSnapshots()) {
if (candidate.getState()==Snapshot.State.BACKED_UP)
return candidate;
}
throw new AssertionError("No suitable Snapshot found.");
}
protected VirtualMachine getPreferredVirtualMachine() {
for (VirtualMachine candidate : client.getVirtualMachineClient().listVirtualMachines()) {
// this is a guess::
if (candidate.getState()==VirtualMachine.State.RUNNING || candidate.getState()==VirtualMachine.State.STOPPED)
return candidate;
}
throw new AssertionError("No suitable VirtualMachine found.");
}
protected Volume createPreferredVolumeFromDisk() {
return Retryables.retryGettingResultOrFailing(new PredicateCallable<Volume>() {
public Volume call() {
AsyncCreateResponse job = client.getVolumeClient().createVolumeFromDiskOfferingInZone(
prefix+"-jclouds-volume", getPreferredDiskOffering().getId(), zoneId);
assertTrue(jobComplete.apply(job.getJobId()));
logger.info("created volume "+job.getId());
return findVolumeWithId(job.getId());
}
}, null, 60*1000, "failed to create volume");
}
public void testCreateVolumeFromDiskofferingInZoneAndDeleteVolume() {
logger.info("testCreateVolumeFromDiskofferingInZoneAndDeleteVolume");
Volume volume = createPreferredVolumeFromDisk();
checkVolume(volume);
// Delete the volume
client.getVolumeClient().deleteVolume(volume.getId());
}
/** test requires that a VM exist */
public void testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete() {
// Pick some disk offering
long diskOfferingId = Iterables.get(client.getOfferingClient().listDiskOfferings(), 0).getId();
logger.info("testCreateVolumeFromDiskofferingInZoneAndAttachVolumeToVirtualMachineAndDetachAndDelete");
final Volume volume = createPreferredVolumeFromDisk();
try {
Volume volume = null;
while (volume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().createVolumeFromDiskOfferingInZone(prefix + "-jclouds-volume",
diskOfferingId, zoneId);
assertTrue(jobComplete.apply(job.getJobId()));
volume = findVolumeWithId(job.getId());
} catch (IllegalStateException e) {
// TODO volume creation failed - retry?
}
checkVolume(volume);
final VirtualMachine virtualMachine = getPreferredVirtualMachine();
Volume attachedVolume = Retryables.retryGettingResultOrFailing(new PredicateCallable<Volume>() {
public Volume call() {
logger.info("attaching volume %s to vm %s", volume, virtualMachine);
AsyncCreateResponse job = client.getVolumeClient().attachVolume(volume.getId(), virtualMachine.getId());
assertTrue(jobComplete.apply(job.getJobId()));
return findVolumeWithId(volume.getId());
}
int failures=0;
protected void onFailure() {
logger.info("failed attaching volume (retrying): %s", getLastFailure());
if (failures++==0) logger.warn(getLastFailure(), "first failure attaching volume");
}
}, null, 60*1000, "failed to attach volume");
checkVolume(attachedVolume);
assertEquals(virtualMachine.getId(), attachedVolume.getVirtualMachineId());
assertNotNull(attachedVolume.getAttached());
Volume detachedVolume = Retryables.retryGettingResultOrFailing(new PredicateCallable<Volume>() {
public Volume call() {
logger.info("detaching volume %s from vm %s", volume, virtualMachine);
AsyncCreateResponse job = client.getVolumeClient().detachVolume(volume.getId());
assertTrue(jobComplete.apply(job.getJobId()));
return findVolumeWithId(volume.getId());
}
protected void onFailure() {
logger.debug("failed detaching volume (retrying): %s", getLastFailure());
}
}, null, 60*1000, "failed to detach volume");
checkVolume(detachedVolume);
assertNull(detachedVolume.getAttached());
} finally {
client.getVolumeClient().deleteVolume(volume.getId());
}
checkVolume(volume);
long virtualMachineId = Iterables.get(client.getVirtualMachineClient().listVirtualMachines(), 0).getId();
// Attach Volume
Volume attachedVolume = null;
while (attachedVolume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().attachVolume(volume.getId(), virtualMachineId);
assertTrue(jobComplete.apply(job.getJobId()));
attachedVolume = findVolumeWithId(volume.getId());
assertEquals(virtualMachineId, attachedVolume.getVirtualMachineId());
assertNotNull(attachedVolume.getAttached());
} catch (IllegalStateException e) {
// TODO volume creation failed - retry?
}
}
// Detach Volume
Volume detachedVolume = null;
while (detachedVolume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().detachVolume(volume.getId());
assertTrue(jobComplete.apply(job.getJobId()));
detachedVolume = findVolumeWithId(volume.getId());
checkVolume(detachedVolume);
} catch (IllegalStateException e) {
//TODO volume creation failed - retry?
}
}
// Cleanup
client.getVolumeClient().deleteVolume(volume.getId());
}
public void testCreateVolumeFromSnapshotInZoneAndDeleteVolume() {
Set<Snapshot> snapshots = client.getSnapshotClient().listSnapshots();
assertNotNull(snapshots);
assertFalse(snapshots.isEmpty());
long snapshotId = Iterables.get(snapshots, 0).getId();
Volume volume = null;
while (volume == null) {
try {
AsyncCreateResponse job = client.getVolumeClient().createVolumeFromSnapshotInZone(prefix + "-jclouds-volume",
snapshotId, zoneId);
logger.info("testCreateVolumeFromSnapshotInZoneAndDeleteVolume (takes ~3m)");
assertNotNull(getPreferredSnapshot());
Volume volume = Retryables.retryGettingResultOrFailing(new PredicateCallable<Volume>() {
public Volume call() {
AsyncCreateResponse job = client.getVolumeClient().createVolumeFromSnapshotInZone(
prefix+"-jclouds-volume", getPreferredSnapshot().getId(), zoneId);
assertTrue(jobComplete.apply(job.getJobId()));
volume = findVolumeWithId(job.getId());
} catch (IllegalStateException e) {
// TODO volume creation failed - retry?
return findVolumeWithId(job.getId());
}
}
protected void onFailure() {
logger.debug("failed creating volume (retrying): %s", getLastFailure());
}
}, null, 60*1000, "failed to create volume");
checkVolume(volume);
// Delete the volume
client.getVolumeClient().deleteVolume(volume.getId());
}
private void checkVolume(final Volume volume) {
static 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;
}
});
Volume findVolumeWithId(final long id) {
return findVolumeWithId(client, id);
}
static Volume findVolumeWithId(final CloudStackClient client, final long id) {
for (Volume v: client.getVolumeClient().listVolumes())
if (v.getId()==id) return v;
throw new NoSuchElementException("no volume with id "+id);
}
// //uncomment to force a cleanup of volumes (since test failures can leave messes)
// public void deleteAllWeUsed() {
// for (Volume v: client.getVolumeClient().listVolumes()) {
// if (v.getName().startsWith(prefix)) {
// logger.warn("found apparent detritus, deleting: %s", v);
// try {
// client.getVolumeClient().deleteVolume(v.getId());
// } catch (Exception e) {
// logger.warn(e, "failed to delete %s: %s", v, e);
// }
// }
// }
// }
}