From 16771961e1c8c192301315ab83e4b72f7fa46ab7 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Wed, 9 Nov 2011 11:36:31 +0200 Subject: [PATCH 1/5] Implement create/list/deleteSnapshot in the Cloudstack API --- .../jclouds/cloudstack/domain/Snapshot.java | 401 ++++++++++++++++++ .../features/SnapshotAsyncClient.java | 90 ++++ .../cloudstack/features/SnapshotClient.java | 66 +++ .../options/CreateSnapshotOptions.java | 67 +++ .../options/ListSnapshotsOptions.java | 158 +++++++ .../features/SnapshotAsyncClientTest.java | 132 ++++++ 6 files changed, 914 insertions(+) create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateSnapshotOptions.java create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java create mode 100644 sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java new file mode 100644 index 0000000000..0fb4ee1a57 --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java @@ -0,0 +1,401 @@ +/** + * 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 com.google.gson.annotations.SerializedName; + +import java.util.Date; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * @author Richard Downer + */ +public class Snapshot implements Comparable { + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private long id; + private String account; + private Date created; + private String domain; + private long domainId; + private SnapshotIntervalType intervalType; + private long jobId; + private String jobStatus; + private String name; + private SnapshotType snapshotType; + private SnapshotState state; + private long volumeId; + private String volumeName; + private String volumeType; + + /** + * @param id ID of the snapshot + */ + public Builder id(long id) { + this.id = id; + return this; + } + + /** + * @param account the account associated with the snapshot + */ + public Builder account(String account) { + this.account = account; + return this; + } + + /** + * @param created the date the snapshot was created + */ + public Builder created(Date created) { + this.created = created; + return this; + } + + /** + * @param domain the domain name of the snapshot's account + */ + public Builder domain(String domain) { + this.domain = domain; + return this; + } + + /** + * @param domainId the domain ID of the snapshot's account + */ + public Builder domainId(long domainId) { + this.domainId = domainId; + return this; + } + + /** + * @param intervalType valid types are hourly, daily, weekly, monthy, template, and none. + */ + public Builder intervalType(SnapshotIntervalType intervalType) { + this.intervalType = intervalType; + return this; + } + + /** + * @param jobId the job ID associated with the snapshot. This is only displayed if the snapshot listed is part of a currently running asynchronous job. + */ + public Builder jobId(long jobId) { + this.jobId = jobId; + return this; + } + + /** + * @param jobStatus the job status associated with the snapshot. This is only displayed if the snapshot listed is part of a currently running asynchronous job. + */ + public Builder jobStatus(String jobStatus) { + this.jobStatus = jobStatus; + return this; + } + + /** + * @param name name of the snapshot + */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** + * @param snapshotType the type of the snapshot + */ + public Builder snapshotType(SnapshotType snapshotType) { + this.snapshotType = snapshotType; + return this; + } + + /** + * @param state the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage + */ + public Builder state(SnapshotState state) { + this.state = state; + return this; + } + + /** + * @param volumeId ID of the disk volume + */ + public Builder volumeId(long volumeId) { + this.volumeId = volumeId; + return this; + } + + /** + * @param volumeName name of the disk volume + */ + public Builder volumeName(String volumeName) { + this.volumeName = volumeName; + return this; + } + + /** + * @param volumeType type of the disk volume + */ + public Builder volumeType(String volumeType) { + this.volumeType = volumeType; + return this; + } + + } + + public enum SnapshotState { + + BackedUp, Creating, BackingUp, UNRECOGNIZED; + + public static SnapshotState fromValue(String type) { + try { + return valueOf(checkNotNull(type, "type")); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + public enum SnapshotType { + + MANUAL, RECURRING, UNRECOGNIZED; + + public static SnapshotType fromValue(String type) { + try { + return valueOf(checkNotNull(type, "type")); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + public enum SnapshotIntervalType { + + HOURLY, DAILY, WEEKLY, MONTHLY, template, none, UNRECOGNIZED; + + public static SnapshotIntervalType fromValue(String type) { + try { + return valueOf(checkNotNull(type, "type")); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + } + + private long id; + private String account; + private Date created; + private String domain; + @SerializedName("domainid") + private long domainId; + @SerializedName("intervaltype") + private SnapshotIntervalType intervalType; + @SerializedName("jobid") + private long jobId; + @SerializedName("jobstatus") + private String jobStatus; + private String name; + @SerializedName("snapshottype") + private SnapshotType snapshotType; + private SnapshotState state; + @SerializedName("volumeid") + private long volumeId; + @SerializedName("volumename") + private String volumeName; + @SerializedName("volumetype") + private String volumeType; // FIXME: replace this with a proper enumerated type (blocked until volume API implemented) + + /** + * present only for serializer + */ + Snapshot() { + } + + /** + * @return ID of the snapshot + */ + public long getId() { + return id; + } + + /** + * @return the account associated with the snapshot + */ + public String getAccount() { + return account; + } + + /** + * @return the date the snapshot was created + */ + public Date getCreated() { + return created; + } + + /** + * @return the domain name of the snapshot's account + */ + public String getDomain() { + return domain; + } + + /** + * @return the domain ID of the snapshot's account + */ + public long getDomainId() { + return domainId; + } + + /** + * @return valid types are hourly, daily, weekly, monthy, template, and none. + */ + public SnapshotIntervalType getIntervalType() { + return intervalType; + } + + /** + * @return the job ID associated with the snapshot. This is only displayed if the snapshot listed is part of a currently running asynchronous job. + */ + public long getJobId() { + return jobId; + } + + /** + * @return the job status associated with the snapshot. This is only displayed if the snapshot listed is part of a currently running asynchronous job. + */ + public String getJobStatus() { + return jobStatus; + } + + /** + * @return name of the snapshot + */ + public String getName() { + return name; + } + + /** + * @return the type of the snapshot + */ + public SnapshotType getSnapshotType() { + return snapshotType; + } + + /** + * @return the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage + */ + public SnapshotState getState() { + return state; + } + + /** + * @return ID of the disk volume + */ + public long getVolumeId() { + return volumeId; + } + + /** + * @return name of the disk volume + */ + public String getVolumeName() { + return volumeName; + } + + /** + * @return type of the disk volume + */ + public String getVolumeType() { + return volumeType; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Snapshot snapshot = (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 (intervalType != snapshot.intervalType) 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; + + return true; + } + + @Override + public int hashCode() { + int result = (int) (id ^ (id >>> 32)); + result = 31 * result + (account != null ? account.hashCode() : 0); + result = 31 * result + (created != null ? created.hashCode() : 0); + result = 31 * result + (domain != null ? domain.hashCode() : 0); + result = 31 * result + (int) (domainId ^ (domainId >>> 32)); + result = 31 * result + (intervalType != null ? intervalType.hashCode() : 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 + (snapshotType != null ? snapshotType.hashCode() : 0); + result = 31 * result + (state != null ? state.hashCode() : 0); + result = 31 * result + (int) (volumeId ^ (volumeId >>> 32)); + result = 31 * result + (volumeName != null ? volumeName.hashCode() : 0); + result = 31 * result + (volumeType != null ? volumeType.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Snapshot[" + + "id=" + id + + ", account='" + account + '\'' + + ", created=" + created + + ", domain='" + domain + '\'' + + ", domainId=" + domainId + + ", intervalType=" + intervalType + + ", jobId=" + jobId + + ", jobStatus='" + jobStatus + '\'' + + ", name='" + name + '\'' + + ", snapshotType=" + snapshotType + + ", state=" + state + + ", volumeId=" + volumeId + + ", volumeName='" + volumeName + '\'' + + ", volumeType='" + volumeType + '\'' + + ']'; + } + + @Override + public int compareTo(Snapshot other) { + return new Long(this.id).compareTo(other.getId()); + } +} diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java new file mode 100644 index 0000000000..03b2e5ef86 --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java @@ -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 com.google.common.util.concurrent.ListenableFuture; +import org.jclouds.cloudstack.domain.AsyncCreateResponse; +import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.filters.QuerySigner; +import org.jclouds.cloudstack.options.CreateSnapshotOptions; +import org.jclouds.cloudstack.options.ListSnapshotsOptions; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.QueryParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.Unwrap; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; + +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; + +/** + * Provides synchronous access to CloudStack Snapshot features. + *

+ * + * @see SnapshotClient + * @see http://download.cloud.com/releases/2.2.0/api/TOC_User.html + * @author Richard Downer + */ +@RequestFilters(QuerySigner.class) +@QueryParams(keys = "response", values = "json") +public interface SnapshotAsyncClient { + + /** + * Creates an instant snapshot of a volume. + * + * @param volumeId The ID of the disk volume + * @param options optional arguments + * @return an asynchronous job structure + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "command", values = "createSnapshot") + @Unwrap + ListenableFuture createSnapshot(@QueryParam("volumeid") long volumeId, CreateSnapshotOptions... options); + + /** + * Lists all available snapshots for the account, matching the query described by the options. + * + * @param options optional arguments + * @return the snapshots matching the query + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "command", values = "listSnapshots") + @Unwrap + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listSnapshots(ListSnapshotsOptions... options); + + /** + * Deletes a snapshot of a disk volume. + * + * @param id The ID of the snapshot + * @return an asynchronous job structure + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "command", values = "deleteSnapshot") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture deleteSnapshot(@QueryParam("id") long id); + +} diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java new file mode 100644 index 0000000000..7c721b529f --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java @@ -0,0 +1,66 @@ +/** + * 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 org.jclouds.cloudstack.domain.AsyncCreateResponse; +import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.options.CreateSnapshotOptions; +import org.jclouds.cloudstack.options.ListSnapshotsOptions; +import org.jclouds.concurrent.Timeout; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * Provides synchronous access to CloudStack Snapshot features. + *

+ * + * @see SnapshotAsyncClient + * @see http://download.cloud.com/releases/2.2.0/api/TOC_User.html + * @author Richard Downer + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface SnapshotClient { + + /** + * Creates an instant snapshot of a volume. + * + * @param volumeId The ID of the disk volume + * @param options optional arguments + * @return an asynchronous job structure + */ + AsyncCreateResponse createSnapshot(long volumeId, CreateSnapshotOptions... options); + + /** + * Lists all available snapshots for the account, matching the query described by the options. + * + * @param options optional arguments + * @return the snapshots matching the query + */ + Set listSnapshots(ListSnapshotsOptions... options); + + /** + * Deletes a snapshot of a disk volume. + * + * @param id The ID of the snapshot + * @return an asynchronous job structure + */ + void deleteSnapshot(long id); + +} diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateSnapshotOptions.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateSnapshotOptions.java new file mode 100644 index 0000000000..40ddc098d7 --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateSnapshotOptions.java @@ -0,0 +1,67 @@ +/** + * 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 for the Snapshot createSnapshot method. + * + * @see org.jclouds.cloudstack.features.SnapshotClient#createSnapshot + * @see org.jclouds.cloudstack.features.SnapshotAsyncClient#createSnapshot + * @author Richard Downer + */ +public class CreateSnapshotOptions extends AccountInDomainOptions { + + public static final CreateSnapshotOptions NONE = new CreateSnapshotOptions(); + + /** + * @param policyId policy id of the snapshot, if this is null, then use MANUAL_POLICY. + */ + public CreateSnapshotOptions policyId(long policyId) { + this.queryParameters.replaceValues("policyid", ImmutableSet.of(policyId + "")); + return this; + } + + public static class Builder { + + /** + * @param account The account of the snapshot. + * @param domainId The domain ID of the snapshot. + */ + public static CreateSnapshotOptions accountInDomain(String account, long domainId) { + return (CreateSnapshotOptions) new CreateSnapshotOptions().accountInDomain(account, domainId); + } + + /** + * @param domainId The domain ID of the snapshot. + */ + public static CreateSnapshotOptions domainId(long domainId) { + return (CreateSnapshotOptions) new CreateSnapshotOptions().domainId(domainId); + } + + /** + * @param policyId policy id of the snapshot, if this is null, then use MANUAL_POLICY. + */ + public static CreateSnapshotOptions policyId(long policyId) { + return new CreateSnapshotOptions().policyId(policyId); + } + } + +} diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java new file mode 100644 index 0000000000..208f8b51cd --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java @@ -0,0 +1,158 @@ +/** + * 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; +import org.jclouds.cloudstack.domain.Snapshot; + +/** + * Options for the Snapshot listSnapshots method. + * + * @see org.jclouds.cloudstack.features.SnapshotClient#listSnapshots + * @see org.jclouds.cloudstack.features.SnapshotAsyncClient#listSnapshots + * @author Richard Downer + */ +public class ListSnapshotsOptions extends AccountInDomainOptions { + + public static final ListSnapshotsOptions NONE = new ListSnapshotsOptions(); + + /** + * @param id lists snapshot by snapshot ID + */ + public ListSnapshotsOptions id(long id) { + this.queryParameters.replaceValues("id", ImmutableSet.of(id + "")); + return this; + } + + /** + * @param intervalType valid values are HOURLY, DAILY, WEEKLY, and MONTHLY. + */ + public ListSnapshotsOptions intervalType(Snapshot.SnapshotIntervalType intervalType) { + this.queryParameters.replaceValues("intervaltype", ImmutableSet.of(intervalType + "")); + return this; + } + + /** + * @param isRecursive defaults to false, but if true, lists all snapshots from the parent specified by the domain id till leaves. + */ + public ListSnapshotsOptions isRecursive(boolean isRecursive) { + this.queryParameters.replaceValues("isrecursive", ImmutableSet.of(isRecursive + "")); + return this; + } + + /** + * @param keyword List by keyword + */ + public ListSnapshotsOptions keyword(String keyword) { + this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword + "")); + return this; + } + + /** + * @param name lists snapshot by snapshot name + */ + public ListSnapshotsOptions name(String name) { + this.queryParameters.replaceValues("name", ImmutableSet.of(name + "")); + return this; + } + + /** + * @param snapshotType valid values are MANUAL or RECURRING. + */ + public ListSnapshotsOptions snapshotType(Snapshot.SnapshotType snapshotType) { + this.queryParameters.replaceValues("snapshottype", ImmutableSet.of(snapshotType + "")); + return this; + } + + /** + * @param volumeId the ID of the disk volume + */ + public ListSnapshotsOptions volumeId(long volumeId) { + this.queryParameters.replaceValues("volumeid", ImmutableSet.of(volumeId + "")); + return this; + } + + public static class Builder { + + /** + * @param account lists snapshot belonging to the specified account. + * @param domainId The domain ID. + */ + public static ListSnapshotsOptions accountInDomain(String account, long domainId) { + return (ListSnapshotsOptions) new ListSnapshotsOptions().accountInDomain(account, domainId); + } + + /** + * @param domainId the domain ID. + */ + public static ListSnapshotsOptions domainId(long domainId) { + return (ListSnapshotsOptions) new ListSnapshotsOptions().domainId(domainId); + } + + /** + * @param id lists snapshot by snapshot ID + */ + public static ListSnapshotsOptions id(long id) { + return new ListSnapshotsOptions().id(id); + } + + /** + * @param intervalType valid values are HOURLY, DAILY, WEEKLY, and MONTHLY. + */ + public static ListSnapshotsOptions intervalType(Snapshot.SnapshotIntervalType intervalType) { + return new ListSnapshotsOptions().intervalType(intervalType); + } + + /** + * @param isRecursive defaults to false, but if true, lists all snapshots from the parent specified by the domain id till leaves. + */ + public static ListSnapshotsOptions isRecursive(boolean isRecursive) { + return new ListSnapshotsOptions().isRecursive(isRecursive); + } + + /** + * @param keyword List by keyword + */ + public static ListSnapshotsOptions keyword(String keyword) { + return new ListSnapshotsOptions().keyword(keyword); + } + + /** + * @param name lists snapshot by snapshot name + */ + public static ListSnapshotsOptions name(String name) { + return new ListSnapshotsOptions().name(name); + } + + /** + * @param snapshotType valid values are MANUAL or RECURRING. + */ + public static ListSnapshotsOptions snapshotType(Snapshot.SnapshotType snapshotType) { + return new ListSnapshotsOptions().snapshotType(snapshotType); + } + + /** + * @param volumeId the ID of the disk volume + */ + public static ListSnapshotsOptions volumeId(long volumeId) { + return new ListSnapshotsOptions().volumeId(volumeId); + } + } + +} diff --git a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java new file mode 100644 index 0000000000..93d4c01bf5 --- /dev/null +++ b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java @@ -0,0 +1,132 @@ +/** + * 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 com.google.inject.TypeLiteral; +import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.options.CreateSnapshotOptions; +import org.jclouds.cloudstack.options.ListSnapshotsOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.functions.ReleasePayloadAndReturn; +import org.jclouds.http.functions.UnwrapOnlyJsonValue; +import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.testng.annotations.Test; + +import java.lang.reflect.Method; + +/** + * Tests the behaviour of SnapshotAsyncClient. + * + * @see SnapshotAsyncClient + * @author Richard Downer + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during +// surefire +@Test(groups = "unit", testName = "SnapshotAsyncClientTest") +public class SnapshotAsyncClientTest extends BaseCloudStackAsyncClientTest { + + public void testCreateSnapshot() throws NoSuchMethodException { + Method method = SnapshotAsyncClient.class.getMethod("createSnapshot", long.class, CreateSnapshotOptions[].class); + HttpRequest httpRequest = processor.createRequest(method, 5); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=createSnapshot&volumeid=5 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + } + + public void testCreateSnapshotOptions() throws NoSuchMethodException { + Method method = SnapshotAsyncClient.class.getMethod("createSnapshot", long.class, CreateSnapshotOptions[].class); + HttpRequest httpRequest = processor.createRequest(method, 5, CreateSnapshotOptions.Builder.accountInDomain("acc", 7).policyId(9)); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=createSnapshot&volumeid=5&account=acc&domainid=7&policyid=9 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + } + + public void testListSnapshots() throws NoSuchMethodException { + Method method = SnapshotAsyncClient.class.getMethod("listSnapshots", ListSnapshotsOptions[].class); + HttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listSnapshots HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + public void testListSnapshotsOptions() throws NoSuchMethodException { + Method method = SnapshotAsyncClient.class.getMethod("listSnapshots", ListSnapshotsOptions[].class); + HttpRequest httpRequest = processor.createRequest(method, ListSnapshotsOptions.Builder.accountInDomain("acc", 7).id(5).intervalType(Snapshot.SnapshotIntervalType.MONTHLY).isRecursive(true).keyword("fred").name("fred's snapshot").snapshotType(Snapshot.SnapshotType.RECURRING).volumeId(11)); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listSnapshots&account=acc&domainid=7&id=5&intervaltype=MONTHLY&isrecursive=true&keyword=fred&name=fred%27s%20snapshot&snapshottype=RECURRING&volumeid=11 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + public void testDeleteSnapshot() throws NoSuchMethodException { + Method method = SnapshotAsyncClient.class.getMethod("deleteSnapshot", long.class); + HttpRequest httpRequest = processor.createRequest(method, 14); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=deleteSnapshot&id=14 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } +} From 48f05f3aed1a8d3c4ebc204ea2f03ab2f3aa4187 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Wed, 9 Nov 2011 11:50:25 +0200 Subject: [PATCH 2/5] Add SnapshotClient.getSnapshot(long id) et al to Cloudstack --- .../features/SnapshotAsyncClient.java | 17 ++++++++++++++++ .../cloudstack/features/SnapshotClient.java | 8 ++++++++ .../features/SnapshotAsyncClientTest.java | 20 +++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java index 03b2e5ef86..867134692c 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java @@ -25,10 +25,13 @@ import org.jclouds.cloudstack.filters.QuerySigner; import org.jclouds.cloudstack.options.CreateSnapshotOptions; import org.jclouds.cloudstack.options.ListSnapshotsOptions; import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.OnlyElement; 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.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import javax.ws.rs.Consumes; @@ -75,6 +78,20 @@ public interface SnapshotAsyncClient { @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> listSnapshots(ListSnapshotsOptions... options); + /** + * Gets a snapshot by its ID. + * + * @param id the snapshot ID + * @return the snapshot with the requested ID + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "command", values = "listSnapshots") + @SelectJson("snapshot") + @OnlyElement + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getSnapshot(@QueryParam("id") long id); + /** * Deletes a snapshot of a disk volume. * diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java index 7c721b529f..97e9a6d97d 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java @@ -55,6 +55,14 @@ public interface SnapshotClient { */ Set listSnapshots(ListSnapshotsOptions... options); + /** + * Gets a snapshot by its ID. + * + * @param id the snapshot ID + * @return the snapshot with the requested ID + */ + Snapshot getSnapshot(long id); + /** * Deletes a snapshot of a disk volume. * diff --git a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java index 93d4c01bf5..7b1e31b85b 100644 --- a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java +++ b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java @@ -18,15 +18,18 @@ */ package org.jclouds.cloudstack.features; +import com.google.common.base.Functions; import com.google.inject.TypeLiteral; import org.jclouds.cloudstack.domain.Snapshot; import org.jclouds.cloudstack.options.CreateSnapshotOptions; import org.jclouds.cloudstack.options.ListSnapshotsOptions; +import org.jclouds.functions.IdentityFunction; import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ReleasePayloadAndReturn; import org.jclouds.http.functions.UnwrapOnlyJsonValue; import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.rest.internal.RestAnnotationProcessor; import org.testng.annotations.Test; @@ -92,6 +95,23 @@ public class SnapshotAsyncClientTest extends BaseCloudStackAsyncClientTest Date: Wed, 9 Nov 2011 17:27:28 +0200 Subject: [PATCH 3/5] Implement create/list/deleteSnapshotPolicy in the Cloudstack API --- .../BindIdListToCommaDelimitedQueryParam.java | 55 ++++++ ...indSnapshotPolicyScheduleToQueryParam.java | 58 ++++++ .../cloudstack/domain/SnapshotPolicy.java | 169 ++++++++++++++++++ .../domain/SnapshotPolicySchedule.java | 41 +++++ .../features/SnapshotAsyncClient.java | 59 ++++++ .../cloudstack/features/SnapshotClient.java | 40 +++++ .../options/ListSnapshotPoliciesOptions.java | 66 +++++++ .../features/SnapshotAsyncClientTest.java | 84 +++++++++ 8 files changed, 572 insertions(+) create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicy.java create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotPoliciesOptions.java diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java new file mode 100644 index 0000000000..9e06beb905 --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java @@ -0,0 +1,55 @@ +/** + * 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.binders; + +import com.google.common.base.Joiner; +import com.google.common.collect.Iterables; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.utils.ModifyRequest; +import org.jclouds.rest.Binder; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +import javax.ws.rs.core.UriBuilder; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * @author Richard Downer + */ +@Singleton +public class BindIdListToCommaDelimitedQueryParam implements Binder { + private final Provider uriBuilderProvider; + + @Inject + public BindIdListToCommaDelimitedQueryParam(Provider uriBuilderProvider) { + this.uriBuilderProvider = checkNotNull(uriBuilderProvider, "uriBuilderProvider"); + } + + @SuppressWarnings("unchecked") + @Override + public R bindToRequest(R request, Object input) { + checkArgument(input instanceof Iterable, "this binder is only valid for Iterables!"); + Iterable numbers = (Iterable) checkNotNull(input, "list of Longs"); + checkArgument(Iterables.size(numbers) > 0, "you must specify at least one element"); + return ModifyRequest.addQueryParam(request, "ids", Joiner.on(',').join(numbers), uriBuilderProvider.get()); + } +} diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java new file mode 100644 index 0000000000..be26c5cc5a --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java @@ -0,0 +1,58 @@ +/** + * 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.binders; + +import com.google.common.base.Joiner; +import com.google.common.collect.Iterables; +import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.utils.ModifyRequest; +import org.jclouds.rest.Binder; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +import javax.ws.rs.core.UriBuilder; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindSnapshotPolicyScheduleToQueryParam implements Binder { + private final Provider uriBuilderProvider; + + @Inject + public BindSnapshotPolicyScheduleToQueryParam(Provider uriBuilderProvider) { + this.uriBuilderProvider = checkNotNull(uriBuilderProvider, "uriBuilderProvider"); + } + + @SuppressWarnings("unchecked") + @Override + public R bindToRequest(R request, Object input) { + checkArgument(input instanceof SnapshotPolicySchedule, "this binder is only valid for SnapshotPolicySchedule"); + SnapshotPolicySchedule schedule = (SnapshotPolicySchedule) input; + R modifiedResult = ModifyRequest.addQueryParam(request, "intervaltype", schedule.getIntervalType(), uriBuilderProvider.get()); + modifiedResult = ModifyRequest.addQueryParam(modifiedResult, "schedule", schedule.getTime(), uriBuilderProvider.get()); + return modifiedResult; + } +} diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicy.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicy.java new file mode 100644 index 0000000000..6546d43b07 --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicy.java @@ -0,0 +1,169 @@ +/** + * 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 com.google.gson.annotations.SerializedName; + +/** + * @author Richard Downer + */ +public class SnapshotPolicy implements Comparable { + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private long id; + private Snapshot.SnapshotIntervalType intervalType; + private long numberToRetain; + private String schedule; + private String timezone; + private long volumeId; + + /** + * @param id the ID of the snapshot policy + */ + public Builder id(long id) { + this.id = id; + return this; + } + + /** + * @param intervalType valid types are hourly, daily, weekly, monthy, template, and none. + */ + public Builder intervalType(Snapshot.SnapshotIntervalType intervalType) { + this.intervalType = intervalType; + return this; + } + + /** + * @param numberToRetain maximum number of snapshots retained + */ + public Builder numberToRetain(long numberToRetain) { + this.numberToRetain = numberToRetain; + return this; + } + + /** + * @param schedule time the snapshot is scheduled to be taken. + */ + public Builder schedule(String schedule) { + this.schedule = schedule; + return this; + } + + /** + * @param timezone the time zone of the snapshot policy + */ + public Builder timezone(String timezone) { + this.timezone = timezone; + return this; + } + + /** + * @param volumeId ID of the disk volume + */ + public Builder volumeId(long volumeId) { + this.volumeId = volumeId; + return this; + } + + } + + private long id; + @SerializedName("intervaltype") + private Snapshot.SnapshotIntervalType intervalType; + @SerializedName("maxsnaps") + private long numberToRetain; + private String schedule; + private String timezone; + @SerializedName("volumeid") + private long volumeId; + + /** + * present only for serializer + */ + SnapshotPolicy() { + } + + /** + * @return the ID of the snapshot policy + */ + public long getId() { + return id; + } + + /** + * @return valid types are hourly, daily, weekly, monthy, template, and none. + */ + public Snapshot.SnapshotIntervalType getIntervalType() { + return intervalType; + } + + /** + * @return maximum number of snapshots retained + */ + public long getNumberToRetain() { + return numberToRetain; + } + + /** + * @return time the snapshot is scheduled to be taken. + */ + public String getSchedule() { + return schedule; + } + + /** + * @return the time zone of the snapshot policy + */ + public String getTimezone() { + return timezone; + } + + /** + * @return ID of the disk volume + */ + public long getVolumeId() { + return volumeId; + } + + @Override + public boolean equals(Object o) { + throw new RuntimeException("FIXME: Implement me"); + } + + @Override + public int hashCode() { + throw new RuntimeException("FIXME: Implement me"); + } + + @Override + public String toString() { + throw new RuntimeException("FIXME: Implement me"); + } + + @Override + public int compareTo(SnapshotPolicy other) { + throw new RuntimeException("FIXME: Implement me"); + } + +} diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java new file mode 100644 index 0000000000..2fdf41c21a --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java @@ -0,0 +1,41 @@ +package org.jclouds.cloudstack.domain; + +/** + * Describes the schedule of a snapshot policy. + * + * @author Richard Downer + */ +public class SnapshotPolicySchedule { + + public static SnapshotPolicySchedule hourly(int minute) { + return new SnapshotPolicySchedule(Snapshot.SnapshotIntervalType.HOURLY, "FIXME"); + } + + public static SnapshotPolicySchedule daily(int hour, int minute) { + return new SnapshotPolicySchedule(Snapshot.SnapshotIntervalType.DAILY, "FIXME"); + } + + public static SnapshotPolicySchedule weekly(int day, int hour, int minute) { + return new SnapshotPolicySchedule(Snapshot.SnapshotIntervalType.WEEKLY, "FIXME"); + } + + public static SnapshotPolicySchedule monthly(int day, int hour, int minute) { + return new SnapshotPolicySchedule(Snapshot.SnapshotIntervalType.MONTHLY, String.format("%02d:%02d:%02d", minute, hour, day)); + } + + private Snapshot.SnapshotIntervalType intervalType; + private String time; + + private SnapshotPolicySchedule(Snapshot.SnapshotIntervalType intervalType, String time) { + this.intervalType = intervalType; + this.time = time; + } + + public Snapshot.SnapshotIntervalType getIntervalType() { + return intervalType; + } + + public String getTime() { + return time; + } +} diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java index 867134692c..7e57cacb99 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotAsyncClient.java @@ -19,11 +19,17 @@ package org.jclouds.cloudstack.features; import com.google.common.util.concurrent.ListenableFuture; +import org.jclouds.cloudstack.binders.BindIdListToCommaDelimitedQueryParam; +import org.jclouds.cloudstack.binders.BindSnapshotPolicyScheduleToQueryParam; import org.jclouds.cloudstack.domain.AsyncCreateResponse; import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.domain.SnapshotPolicy; +import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; import org.jclouds.cloudstack.filters.QuerySigner; import org.jclouds.cloudstack.options.CreateSnapshotOptions; +import org.jclouds.cloudstack.options.ListSnapshotPoliciesOptions; import org.jclouds.cloudstack.options.ListSnapshotsOptions; +import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.OnlyElement; import org.jclouds.rest.annotations.QueryParams; @@ -104,4 +110,57 @@ public interface SnapshotAsyncClient { @ExceptionParser(ReturnVoidOnNotFoundOr404.class) ListenableFuture deleteSnapshot(@QueryParam("id") long id); + /** + * Creates a snapshot policy for the account. + * + * @param schedule how to schedule snapshots + * @param numberToRetain maximum number of snapshots to retain + * @param timezone Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format. + * @param volumeId the ID of the disk volume + * @return the newly-created snapshot policy + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Unwrap + @QueryParams(keys = "command", values = "createSnapshotPolicy") + ListenableFuture createSnapshotPolicy(@BinderParam(BindSnapshotPolicyScheduleToQueryParam.class) SnapshotPolicySchedule schedule, @QueryParam("maxsnaps") long numberToRetain, @QueryParam("timezone") String timezone, @QueryParam("volumeid") long volumeId); + + /** + * Deletes a snapshot policy for the account. + * + * @param id The ID of the snapshot policy + * @return + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "command", values = "deleteSnapshotPolicies") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture deleteSnapshotPolicy(@QueryParam("id") long id); + + /** + * Deletes snapshot policies for the account. + * + * @param id IDs of snapshot policies + * @return + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "command", values = "deleteSnapshotPolicies") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture deleteSnapshotPolicies(@BinderParam(BindIdListToCommaDelimitedQueryParam.class) Iterable id); + + /** + * Lists snapshot policies. + * + * @param volumeId the ID of the disk volume + * @param options optional arguments + * @return the snapshot policies matching the query + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "command", values = "listSnapshotPolicies") + @Unwrap + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listSnapshotPolicies(@QueryParam("volumeid") long volumeId, ListSnapshotPoliciesOptions... options); + } diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java index 97e9a6d97d..f1274a2d60 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/SnapshotClient.java @@ -20,10 +20,14 @@ package org.jclouds.cloudstack.features; import org.jclouds.cloudstack.domain.AsyncCreateResponse; import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.domain.SnapshotPolicy; +import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; import org.jclouds.cloudstack.options.CreateSnapshotOptions; +import org.jclouds.cloudstack.options.ListSnapshotPoliciesOptions; import org.jclouds.cloudstack.options.ListSnapshotsOptions; import org.jclouds.concurrent.Timeout; +import javax.ws.rs.QueryParam; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -71,4 +75,40 @@ public interface SnapshotClient { */ void deleteSnapshot(long id); + /** + * Creates a snapshot policy for the account. + * + * @param schedule how to schedule snapshots + * @param numberToRetain maximum number of snapshots to retain + * @param timezone Specifies a timezone for this command. For more information on the timezone parameter, see Time Zone Format. + * @param volumeId the ID of the disk volume + * @return the newly-created snapshot policy + */ + SnapshotPolicy createSnapshotPolicy(SnapshotPolicySchedule schedule, long numberToRetain, String timezone, long volumeId); + + /** + * Deletes a snapshot policy for the account. + * + * @param id The ID of the snapshot policy + * @return + */ + void deleteSnapshotPolicy(long id); + + /** + * Deletes snapshot policies for the account. + * + * @param id IDs of snapshot policies + * @return + */ + void deleteSnapshotPolicies(Iterable id); + + /** + * Lists snapshot policies. + * + * @param volumeId the ID of the disk volume + * @param options optional arguments + * @return the snapshot policies matching the query + */ + Set listSnapshotPolicies(long volumeId, ListSnapshotPoliciesOptions... options); + } diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotPoliciesOptions.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotPoliciesOptions.java new file mode 100644 index 0000000000..790ba6f88d --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotPoliciesOptions.java @@ -0,0 +1,66 @@ +/** + * 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 for the Snapshot listSnapshotPolicies method. + * + * @see org.jclouds.cloudstack.features.SnapshotClient#listSnapshotPolicies + * @see org.jclouds.cloudstack.features.SnapshotAsyncClient#listSnapshotPolicies + * @author Richard Downer + */ +public class ListSnapshotPoliciesOptions extends AccountInDomainOptions { + + public static final ListSnapshotPoliciesOptions NONE = new ListSnapshotPoliciesOptions(); + + /** + * @param keyword List by keyword + */ + public ListSnapshotPoliciesOptions keyword(String keyword) { + this.queryParameters.replaceValues("keyword", ImmutableSet.of(keyword + "")); + return this; + } + + public static class Builder { + + /** + * @param account lists snapshot policies for the specified account. + */ + public static ListSnapshotPoliciesOptions accountInDomain(String account, long domainId) { + return (ListSnapshotPoliciesOptions) new ListSnapshotPoliciesOptions().accountInDomain(account, domainId); + } + + /** + * @param domainId the domain ID. + */ + public static ListSnapshotPoliciesOptions domainId(long domainId) { + return (ListSnapshotPoliciesOptions) new ListSnapshotPoliciesOptions().domainId(domainId); + } + + /** + * @param keyword List by keyword + */ + public static ListSnapshotPoliciesOptions keyword(String keyword) { + return new ListSnapshotPoliciesOptions().keyword(keyword); + } + } + +} diff --git a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java index 7b1e31b85b..7444cda9fe 100644 --- a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java +++ b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java @@ -19,9 +19,12 @@ package org.jclouds.cloudstack.features; import com.google.common.base.Functions; +import com.google.common.collect.ImmutableSet; import com.google.inject.TypeLiteral; import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; import org.jclouds.cloudstack.options.CreateSnapshotOptions; +import org.jclouds.cloudstack.options.ListSnapshotPoliciesOptions; import org.jclouds.cloudstack.options.ListSnapshotsOptions; import org.jclouds.functions.IdentityFunction; import org.jclouds.http.HttpRequest; @@ -144,6 +147,87 @@ public class SnapshotAsyncClientTest extends BaseCloudStackAsyncClientTest ids = ImmutableSet.of(3L, 5L, 7L); + HttpRequest httpRequest = processor.createRequest(method, ids); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=deleteSnapshotPolicies&ids=3%2C5%2C7 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + public void testListSnapshotPolicies() throws NoSuchMethodException { + Method method = SnapshotAsyncClient.class.getMethod("listSnapshotPolicies", long.class, ListSnapshotPoliciesOptions[].class); + HttpRequest httpRequest = processor.createRequest(method, 10); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listSnapshotPolicies&volumeid=10 HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + + public void testListSnapshotPoliciesOptions() throws NoSuchMethodException { + Method method = SnapshotAsyncClient.class.getMethod("listSnapshotPolicies", long.class, ListSnapshotPoliciesOptions[].class); + HttpRequest httpRequest = processor.createRequest(method, 10, ListSnapshotPoliciesOptions.Builder.accountInDomain("fred", 4).keyword("bob")); + + assertRequestLineEquals(httpRequest, + "GET http://localhost:8080/client/api?response=json&command=listSnapshotPolicies&volumeid=10&account=fred&domainid=4&keyword=bob HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyJsonValue.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(httpRequest); + } + @Override protected TypeLiteral> createTypeLiteral() { return new TypeLiteral>() { From 1ba06c8973858424fc857df141cf67cb573378c9 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Wed, 9 Nov 2011 18:06:32 +0200 Subject: [PATCH 4/5] Some renaming in Cloudstack Snapshot API impl to remove unnecessary words --- ...indSnapshotPolicyScheduleToQueryParam.java | 4 +- .../jclouds/cloudstack/domain/Snapshot.java | 48 +++++++++---------- .../cloudstack/domain/SnapshotPolicy.java | 14 +++--- .../domain/SnapshotPolicySchedule.java | 18 +++---- .../options/ListSnapshotsOptions.java | 16 +++---- .../features/SnapshotAsyncClientTest.java | 2 +- 6 files changed, 50 insertions(+), 52 deletions(-) diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java index be26c5cc5a..15b7f5f5c1 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java @@ -18,8 +18,6 @@ */ package org.jclouds.cloudstack.binders; -import com.google.common.base.Joiner; -import com.google.common.collect.Iterables; import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; import org.jclouds.http.HttpRequest; import org.jclouds.http.utils.ModifyRequest; @@ -51,7 +49,7 @@ public class BindSnapshotPolicyScheduleToQueryParam implements Binder { public R bindToRequest(R request, Object input) { checkArgument(input instanceof SnapshotPolicySchedule, "this binder is only valid for SnapshotPolicySchedule"); SnapshotPolicySchedule schedule = (SnapshotPolicySchedule) input; - R modifiedResult = ModifyRequest.addQueryParam(request, "intervaltype", schedule.getIntervalType(), uriBuilderProvider.get()); + R modifiedResult = ModifyRequest.addQueryParam(request, "intervaltype", schedule.getInterval(), uriBuilderProvider.get()); modifiedResult = ModifyRequest.addQueryParam(modifiedResult, "schedule", schedule.getTime(), uriBuilderProvider.get()); return modifiedResult; } diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java index 0fb4ee1a57..ae58c53412 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Snapshot.java @@ -40,12 +40,12 @@ public class Snapshot implements Comparable { private Date created; private String domain; private long domainId; - private SnapshotIntervalType intervalType; + private Interval interval; private long jobId; private String jobStatus; private String name; - private SnapshotType snapshotType; - private SnapshotState state; + private Type snapshotType; + private State state; private long volumeId; private String volumeName; private String volumeType; @@ -91,10 +91,10 @@ public class Snapshot implements Comparable { } /** - * @param intervalType valid types are hourly, daily, weekly, monthy, template, and none. + * @param interval valid types are hourly, daily, weekly, monthy, template, and none. */ - public Builder intervalType(SnapshotIntervalType intervalType) { - this.intervalType = intervalType; + public Builder interval(Interval interval) { + this.interval = interval; return this; } @@ -125,7 +125,7 @@ public class Snapshot implements Comparable { /** * @param snapshotType the type of the snapshot */ - public Builder snapshotType(SnapshotType snapshotType) { + public Builder snapshotType(Type snapshotType) { this.snapshotType = snapshotType; return this; } @@ -133,7 +133,7 @@ public class Snapshot implements Comparable { /** * @param state the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage */ - public Builder state(SnapshotState state) { + public Builder state(State state) { this.state = state; return this; } @@ -164,11 +164,11 @@ public class Snapshot implements Comparable { } - public enum SnapshotState { + public static enum State { BackedUp, Creating, BackingUp, UNRECOGNIZED; - public static SnapshotState fromValue(String type) { + public static State fromValue(String type) { try { return valueOf(checkNotNull(type, "type")); } catch (IllegalArgumentException e) { @@ -177,11 +177,11 @@ public class Snapshot implements Comparable { } } - public enum SnapshotType { + public static enum Type { MANUAL, RECURRING, UNRECOGNIZED; - public static SnapshotType fromValue(String type) { + public static Type fromValue(String type) { try { return valueOf(checkNotNull(type, "type")); } catch (IllegalArgumentException e) { @@ -190,11 +190,11 @@ public class Snapshot implements Comparable { } } - public enum SnapshotIntervalType { + public static enum Interval { HOURLY, DAILY, WEEKLY, MONTHLY, template, none, UNRECOGNIZED; - public static SnapshotIntervalType fromValue(String type) { + public static Interval fromValue(String type) { try { return valueOf(checkNotNull(type, "type")); } catch (IllegalArgumentException e) { @@ -210,15 +210,15 @@ public class Snapshot implements Comparable { @SerializedName("domainid") private long domainId; @SerializedName("intervaltype") - private SnapshotIntervalType intervalType; + private Interval interval; @SerializedName("jobid") private long jobId; @SerializedName("jobstatus") private String jobStatus; private String name; @SerializedName("snapshottype") - private SnapshotType snapshotType; - private SnapshotState state; + private Type snapshotType; + private State state; @SerializedName("volumeid") private long volumeId; @SerializedName("volumename") @@ -270,8 +270,8 @@ public class Snapshot implements Comparable { /** * @return valid types are hourly, daily, weekly, monthy, template, and none. */ - public SnapshotIntervalType getIntervalType() { - return intervalType; + public Interval getInterval() { + return interval; } /** @@ -298,14 +298,14 @@ public class Snapshot implements Comparable { /** * @return the type of the snapshot */ - public SnapshotType getSnapshotType() { + public Type getSnapshotType() { return snapshotType; } /** * @return the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage */ - public SnapshotState getState() { + public State getState() { return state; } @@ -344,7 +344,7 @@ public class Snapshot implements Comparable { 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 (intervalType != snapshot.intervalType) 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; @@ -362,7 +362,7 @@ public class Snapshot implements Comparable { result = 31 * result + (created != null ? created.hashCode() : 0); result = 31 * result + (domain != null ? domain.hashCode() : 0); result = 31 * result + (int) (domainId ^ (domainId >>> 32)); - result = 31 * result + (intervalType != null ? intervalType.hashCode() : 0); + result = 31 * result + (interval != null ? interval.hashCode() : 0); result = 31 * result + (int) (jobId ^ (jobId >>> 32)); result = 31 * result + (jobStatus != null ? jobStatus.hashCode() : 0); result = 31 * result + (name != null ? name.hashCode() : 0); @@ -382,7 +382,7 @@ public class Snapshot implements Comparable { ", created=" + created + ", domain='" + domain + '\'' + ", domainId=" + domainId + - ", intervalType=" + intervalType + + ", interval=" + interval + ", jobId=" + jobId + ", jobStatus='" + jobStatus + '\'' + ", name='" + name + '\'' + diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicy.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicy.java index 6546d43b07..a1aed92392 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicy.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicy.java @@ -32,7 +32,7 @@ public class SnapshotPolicy implements Comparable { public static class Builder { private long id; - private Snapshot.SnapshotIntervalType intervalType; + private Snapshot.Interval interval; private long numberToRetain; private String schedule; private String timezone; @@ -47,10 +47,10 @@ public class SnapshotPolicy implements Comparable { } /** - * @param intervalType valid types are hourly, daily, weekly, monthy, template, and none. + * @param interval valid types are hourly, daily, weekly, monthy, template, and none. */ - public Builder intervalType(Snapshot.SnapshotIntervalType intervalType) { - this.intervalType = intervalType; + public Builder interval(Snapshot.Interval interval) { + this.interval = interval; return this; } @@ -90,7 +90,7 @@ public class SnapshotPolicy implements Comparable { private long id; @SerializedName("intervaltype") - private Snapshot.SnapshotIntervalType intervalType; + private Snapshot.Interval interval; @SerializedName("maxsnaps") private long numberToRetain; private String schedule; @@ -114,8 +114,8 @@ public class SnapshotPolicy implements Comparable { /** * @return valid types are hourly, daily, weekly, monthy, template, and none. */ - public Snapshot.SnapshotIntervalType getIntervalType() { - return intervalType; + public Snapshot.Interval getInterval() { + return interval; } /** diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java index 2fdf41c21a..cb7cd63b00 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java @@ -8,31 +8,31 @@ package org.jclouds.cloudstack.domain; public class SnapshotPolicySchedule { public static SnapshotPolicySchedule hourly(int minute) { - return new SnapshotPolicySchedule(Snapshot.SnapshotIntervalType.HOURLY, "FIXME"); + return new SnapshotPolicySchedule(Snapshot.Interval.HOURLY, "FIXME"); } public static SnapshotPolicySchedule daily(int hour, int minute) { - return new SnapshotPolicySchedule(Snapshot.SnapshotIntervalType.DAILY, "FIXME"); + return new SnapshotPolicySchedule(Snapshot.Interval.DAILY, "FIXME"); } public static SnapshotPolicySchedule weekly(int day, int hour, int minute) { - return new SnapshotPolicySchedule(Snapshot.SnapshotIntervalType.WEEKLY, "FIXME"); + return new SnapshotPolicySchedule(Snapshot.Interval.WEEKLY, "FIXME"); } public static SnapshotPolicySchedule monthly(int day, int hour, int minute) { - return new SnapshotPolicySchedule(Snapshot.SnapshotIntervalType.MONTHLY, String.format("%02d:%02d:%02d", minute, hour, day)); + return new SnapshotPolicySchedule(Snapshot.Interval.MONTHLY, String.format("%02d:%02d:%02d", minute, hour, day)); } - private Snapshot.SnapshotIntervalType intervalType; + private Snapshot.Interval interval; private String time; - private SnapshotPolicySchedule(Snapshot.SnapshotIntervalType intervalType, String time) { - this.intervalType = intervalType; + private SnapshotPolicySchedule(Snapshot.Interval interval, String time) { + this.interval = interval; this.time = time; } - public Snapshot.SnapshotIntervalType getIntervalType() { - return intervalType; + public Snapshot.Interval getInterval() { + return interval; } public String getTime() { diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java index 208f8b51cd..6a4ef54a2a 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/ListSnapshotsOptions.java @@ -41,10 +41,10 @@ public class ListSnapshotsOptions extends AccountInDomainOptions { } /** - * @param intervalType valid values are HOURLY, DAILY, WEEKLY, and MONTHLY. + * @param interval valid values are HOURLY, DAILY, WEEKLY, and MONTHLY. */ - public ListSnapshotsOptions intervalType(Snapshot.SnapshotIntervalType intervalType) { - this.queryParameters.replaceValues("intervaltype", ImmutableSet.of(intervalType + "")); + public ListSnapshotsOptions interval(Snapshot.Interval interval) { + this.queryParameters.replaceValues("intervaltype", ImmutableSet.of(interval + "")); return this; } @@ -75,7 +75,7 @@ public class ListSnapshotsOptions extends AccountInDomainOptions { /** * @param snapshotType valid values are MANUAL or RECURRING. */ - public ListSnapshotsOptions snapshotType(Snapshot.SnapshotType snapshotType) { + public ListSnapshotsOptions snapshotType(Snapshot.Type snapshotType) { this.queryParameters.replaceValues("snapshottype", ImmutableSet.of(snapshotType + "")); return this; } @@ -113,10 +113,10 @@ public class ListSnapshotsOptions extends AccountInDomainOptions { } /** - * @param intervalType valid values are HOURLY, DAILY, WEEKLY, and MONTHLY. + * @param interval valid values are HOURLY, DAILY, WEEKLY, and MONTHLY. */ - public static ListSnapshotsOptions intervalType(Snapshot.SnapshotIntervalType intervalType) { - return new ListSnapshotsOptions().intervalType(intervalType); + public static ListSnapshotsOptions interval(Snapshot.Interval interval) { + return new ListSnapshotsOptions().interval(interval); } /** @@ -143,7 +143,7 @@ public class ListSnapshotsOptions extends AccountInDomainOptions { /** * @param snapshotType valid values are MANUAL or RECURRING. */ - public static ListSnapshotsOptions snapshotType(Snapshot.SnapshotType snapshotType) { + public static ListSnapshotsOptions snapshotType(Snapshot.Type snapshotType) { return new ListSnapshotsOptions().snapshotType(snapshotType); } diff --git a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java index 7444cda9fe..d474ae82ed 100644 --- a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java +++ b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java @@ -117,7 +117,7 @@ public class SnapshotAsyncClientTest extends BaseCloudStackAsyncClientTest Date: Wed, 9 Nov 2011 18:18:34 +0200 Subject: [PATCH 5/5] Move static methods out of SnapshotPolicySchedule into new class util.SnapshotPolicySchedules (and fix the FIXMEs and a missing license header at the same time) --- .../domain/SnapshotPolicySchedule.java | 37 ++++++++------- .../util/SnapshotPolicySchedules.java | 45 +++++++++++++++++++ .../features/SnapshotAsyncClientTest.java | 3 +- 3 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/util/SnapshotPolicySchedules.java diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java index cb7cd63b00..1603446cc1 100644 --- a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/SnapshotPolicySchedule.java @@ -1,32 +1,35 @@ +/** + * 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; /** * Describes the schedule of a snapshot policy. * + * @see org.jclouds.cloudstack.util.SnapshotPolicySchedules * @author Richard Downer */ public class SnapshotPolicySchedule { - public static SnapshotPolicySchedule hourly(int minute) { - return new SnapshotPolicySchedule(Snapshot.Interval.HOURLY, "FIXME"); - } - - public static SnapshotPolicySchedule daily(int hour, int minute) { - return new SnapshotPolicySchedule(Snapshot.Interval.DAILY, "FIXME"); - } - - public static SnapshotPolicySchedule weekly(int day, int hour, int minute) { - return new SnapshotPolicySchedule(Snapshot.Interval.WEEKLY, "FIXME"); - } - - public static SnapshotPolicySchedule monthly(int day, int hour, int minute) { - return new SnapshotPolicySchedule(Snapshot.Interval.MONTHLY, String.format("%02d:%02d:%02d", minute, hour, day)); - } - private Snapshot.Interval interval; private String time; - private SnapshotPolicySchedule(Snapshot.Interval interval, String time) { + public SnapshotPolicySchedule(Snapshot.Interval interval, String time) { this.interval = interval; this.time = time; } diff --git a/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/util/SnapshotPolicySchedules.java b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/util/SnapshotPolicySchedules.java new file mode 100644 index 0000000000..44b6f240d7 --- /dev/null +++ b/sandbox-apis/cloudstack/src/main/java/org/jclouds/cloudstack/util/SnapshotPolicySchedules.java @@ -0,0 +1,45 @@ +/** + * 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.util; + +import org.jclouds.cloudstack.domain.Snapshot; +import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; + +/** + * Methods to create SnapshotPolicySchedule objects in the format required by Cloudstack. + * + * @author Richard Downer + */ +public class SnapshotPolicySchedules { + public static SnapshotPolicySchedule hourly(int minute) { + return new SnapshotPolicySchedule(Snapshot.Interval.HOURLY, String.format("%02d", minute)); + } + + public static SnapshotPolicySchedule daily(int hour, int minute) { + return new SnapshotPolicySchedule(Snapshot.Interval.DAILY, String.format("%02d:%02d", minute, hour)); + } + + public static SnapshotPolicySchedule weekly(int day, int hour, int minute) { + return new SnapshotPolicySchedule(Snapshot.Interval.WEEKLY, String.format("%02d:%02d:%02d", minute, hour, day)); + } + + public static SnapshotPolicySchedule monthly(int day, int hour, int minute) { + return new SnapshotPolicySchedule(Snapshot.Interval.MONTHLY, String.format("%02d:%02d:%02d", minute, hour, day)); + } +} diff --git a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java index d474ae82ed..f50ad8c4e6 100644 --- a/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java +++ b/sandbox-apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SnapshotAsyncClientTest.java @@ -26,6 +26,7 @@ import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; import org.jclouds.cloudstack.options.CreateSnapshotOptions; import org.jclouds.cloudstack.options.ListSnapshotPoliciesOptions; import org.jclouds.cloudstack.options.ListSnapshotsOptions; +import org.jclouds.cloudstack.util.SnapshotPolicySchedules; import org.jclouds.functions.IdentityFunction; import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ReleasePayloadAndReturn; @@ -149,7 +150,7 @@ public class SnapshotAsyncClientTest extends BaseCloudStackAsyncClientTest