@@ -37,6 +39,15 @@ import javax.ws.rs.PathParam;
@Beta
public interface GoogleComputeApi {
+ /**
+ * Provides synchronous access to Disk features
+ *
+ * @param projectName the name of the project
+ */
+ @Delegate
+ @Path("/projects/{project}")
+ DiskApi getDiskApiForProject(@PathParam("project") String projectName);
+
/**
* Provides synchronous access to Project features
*/
diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeAsyncApi.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeAsyncApi.java
index 2cddad8bab..020fa9007b 100644
--- a/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeAsyncApi.java
+++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/GoogleComputeAsyncApi.java
@@ -19,6 +19,7 @@
package org.jclouds.googlecompute;
import com.google.common.annotations.Beta;
+import org.jclouds.googlecompute.features.DiskAsyncApi;
import org.jclouds.googlecompute.features.OperationAsyncApi;
import org.jclouds.googlecompute.features.ProjectAsyncApi;
import org.jclouds.googlecompute.features.ZoneAsyncApi;
@@ -37,6 +38,15 @@ import javax.ws.rs.PathParam;
@Beta
public interface GoogleComputeAsyncApi {
+ /**
+ * Provides asynchronous access to Disk features
+ *
+ * @param projectName the name of the project
+ */
+ @Delegate
+ @Path("/projects/{project}")
+ DiskAsyncApi getDiskApiForProject(@PathParam("project") String projectName);
+
/**
* Provides asynchronous access to Project features
*/
diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/config/GoogleComputeRestClientModule.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/config/GoogleComputeRestClientModule.java
index 851cc8627c..211ee5ee84 100644
--- a/labs/google-compute/src/main/java/org/jclouds/googlecompute/config/GoogleComputeRestClientModule.java
+++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/config/GoogleComputeRestClientModule.java
@@ -27,6 +27,8 @@ import com.google.inject.TypeLiteral;
import org.jclouds.googlecompute.GoogleComputeApi;
import org.jclouds.googlecompute.GoogleComputeAsyncApi;
import org.jclouds.googlecompute.domain.Operation;
+import org.jclouds.googlecompute.features.DiskApi;
+import org.jclouds.googlecompute.features.DiskAsyncApi;
import org.jclouds.googlecompute.features.OperationApi;
import org.jclouds.googlecompute.features.OperationAsyncApi;
import org.jclouds.googlecompute.features.ProjectApi;
@@ -58,6 +60,7 @@ import static com.google.common.base.Preconditions.checkState;
@ConfiguresRestClient
public class GoogleComputeRestClientModule extends RestClientModule {
public static final Map, Class>> DELEGATE_MAP = ImmutableMap., Class>>builder()
+ .put(DiskApi.class, DiskAsyncApi.class)
.put(OperationApi.class, OperationAsyncApi.class)
.put(ProjectApi.class, ProjectAsyncApi.class)
.put(ZoneApi.class, ZoneAsyncApi.class)
diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/domain/Disk.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/domain/Disk.java
new file mode 100644
index 0000000000..2d64536faa
--- /dev/null
+++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/domain/Disk.java
@@ -0,0 +1,156 @@
+/*
+ * 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.googlecompute.domain;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+import java.util.Date;
+
+import static com.google.common.base.Optional.fromNullable;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A persistent disk resource
+ *
+ * @author David Alves
+ * @see
+ */
+@Beta
+public final class Disk extends Resource {
+
+ private final Integer sizeGb;
+ private final URI zone;
+ private final String status;
+
+ @ConstructorProperties({
+ "id", "creationTimestamp", "selfLink", "name", "description", "sizeGb", "zone",
+ "status"
+ })
+ private Disk(String id, Date creationTimestamp, URI selfLink, String name, String description,
+ Integer sizeGb, URI zone, String status) {
+ super(Kind.DISK, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp), checkNotNull(selfLink,
+ "selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description));
+ this.sizeGb = checkNotNull(sizeGb, "sizeGb of %s", name);
+ this.zone = checkNotNull(zone, "zone of %s", name);
+ this.status = checkNotNull(status, "status of %s", name);
+ }
+
+ /**
+ * @return size of the persistent disk, specified in GB.
+ */
+ public int getSizeGb() {
+ return sizeGb;
+ }
+
+ /**
+ * @return URL for the zone where the persistent disk resides.
+ */
+ public URI getZone() {
+ return zone;
+ }
+
+ /**
+ * @return the status of disk creation.
+ */
+ public String getStatus() {
+ return status;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Objects.ToStringHelper string() {
+ return super.string()
+ .omitNullValues()
+ .add("sizeGb", sizeGb)
+ .add("zone", zone)
+ .add("status", status);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return string().toString();
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().fromDisk(this);
+ }
+
+ public static final class Builder extends Resource.Builder {
+
+ private Integer sizeGb;
+ private URI zone;;
+ private String status;
+
+ /**
+ * @see Disk#getSizeGb()
+ */
+ public Builder sizeGb(Integer sizeGb) {
+ this.sizeGb = sizeGb;
+ return this;
+ }
+
+ /**
+ * @see Disk#getZone()
+ */
+ public Builder zone(URI zone) {
+ this.zone = zone;
+ return this;
+ }
+
+ /**
+ * @see Disk#getStatus()
+ */
+ public Builder status(String status) {
+ this.status = status;
+ return this;
+ }
+
+
+ @Override
+ protected Builder self() {
+ return this;
+ }
+
+ public Disk build() {
+ return new Disk(super.id, super.creationTimestamp, super.selfLink, super.name,
+ super.description, sizeGb, zone, status);
+ }
+
+ public Builder fromDisk(Disk in) {
+ return super.fromResource(in)
+ .sizeGb(in.getSizeGb())
+ .zone(in.getZone())
+ .status(in.getStatus());
+ }
+
+ }
+
+}
diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/DiskApi.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/DiskApi.java
new file mode 100644
index 0000000000..026efbd280
--- /dev/null
+++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/DiskApi.java
@@ -0,0 +1,105 @@
+/*
+ * 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.googlecompute.features;
+
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecompute.domain.Disk;
+import org.jclouds.googlecompute.domain.ListPage;
+import org.jclouds.googlecompute.domain.Operation;
+import org.jclouds.googlecompute.options.ListOptions;
+import org.jclouds.javax.annotation.Nullable;
+
+import java.net.URI;
+
+/**
+ * Provides synchronous access to Disks via their REST API.
+ *
+ * @author David Alves
+ * @see DiskAsyncApi
+ * @see
+ */
+public interface DiskApi {
+
+ /**
+ * Returns the specified persistent disk resource.
+ *
+ * @param diskName name of the persistent disk resource to return.
+ * @return a Disk resource.
+ */
+ Disk get(String diskName);
+
+ /**
+ * Creates a persistent disk resource in the specified project specifying the size of the disk.
+ *
+ * @param diskName the name of disk.
+ * @param zone the URi of the zone where the disk is to be created.
+ * @param sizeGb the size of the disk
+ * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+ * you, and look for the status field.
+ */
+ Operation insert(String diskName, URI zone, int sizeGb);
+
+ /**
+ * Deletes the specified persistent disk resource.
+ *
+ * @param diskName name of the persistent disk resource to delete.
+ * @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
+ * you, and look for the status field.
+ */
+ Operation delete(String diskName);
+
+ /**
+ * @see DiskApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
+ */
+ public ListPage listFirstPage();
+
+ /**
+ * @see DiskApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
+ */
+ public ListPage listAtMarker(@Nullable String marker);
+
+
+ /**
+ * Retrieves the listPage of persistent disk resources contained within the specified project.
+ * By default the listPage as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has
+ * not been set.
+ *
+ * @param marker marks the beginning of the next list page
+ * @param listOptions listing options
+ * @return a page of the listPage
+ * @see ListOptions
+ * @see org.jclouds.googlecompute.domain.ListPage
+ */
+ ListPage listAtMarker(@Nullable String marker, ListOptions listOptions);
+
+ /**
+ * @see DiskApi#list(org.jclouds.googlecompute.options.ListOptions)
+ */
+ public PagedIterable list();
+
+ /**
+ * A paged version of DiskApi#listPage()
+ *
+ * @return a Paged, Fluent Iterable that is able to fetch additional pages when required
+ * @see PagedIterable
+ * @see DiskApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
+ */
+ PagedIterable list(ListOptions listOptions);
+}
diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/DiskAsyncApi.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/DiskAsyncApi.java
new file mode 100644
index 0000000000..f4f0c99bb1
--- /dev/null
+++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/features/DiskAsyncApi.java
@@ -0,0 +1,157 @@
+/*
+ * 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.googlecompute.features;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.googlecompute.domain.Disk;
+import org.jclouds.googlecompute.domain.ListPage;
+import org.jclouds.googlecompute.domain.Operation;
+import org.jclouds.googlecompute.functions.internal.ParseDisks;
+import org.jclouds.googlecompute.options.ListOptions;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.config.OAuthScopes;
+import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.net.URI;
+
+import static org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
+import static org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import static org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE;
+import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_SCOPE;
+
+/**
+ * Provides asynchronous access to Disks via their REST API.
+ *
+ * @author David Alves
+ * @see DiskApi
+ */
+@SkipEncoding({'/', '='})
+@RequestFilters(OAuthAuthenticator.class)
+public interface DiskAsyncApi {
+
+ /**
+ * @see DiskApi#get(String)
+ */
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/disks/{disk}")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @Fallback(NullOnNotFoundOr404.class)
+ ListenableFuture get(@PathParam("disk") String diskName);
+
+ /**
+ * @see DiskApi#insert(String, java.net.URI, int)
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/disks")
+ @OAuthScopes({COMPUTE_SCOPE})
+ @MapBinder(BindToJsonPayload.class)
+ ListenableFuture insert(@PayloadParam("name") String diskName,
+ @PayloadParam("zone") URI zone,
+ @PayloadParam("sizeGb") int sizeGb);
+
+ /**
+ * @see DiskApi#delete(String)
+ */
+ @DELETE
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/disks/{disk}")
+ @OAuthScopes(COMPUTE_SCOPE)
+ @Fallback(NullOnNotFoundOr404.class)
+ ListenableFuture delete(@PathParam("disk") String diskName);
+
+ /**
+ * @see org.jclouds.googlecompute.features.DiskApi#listFirstPage()
+ */
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/disks")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(ParseDisks.class)
+ @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+ ListenableFuture> listFirstPage();
+
+ /**
+ * @see DiskApi#listAtMarker(String)
+ */
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/disks")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(ParseDisks.class)
+ @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+ ListenableFuture> listAtMarker(@QueryParam("pageToken") @Nullable String marker);
+
+ /**
+ * @see DiskApi#listAtMarker(String, org.jclouds.googlecompute.options.ListOptions)
+ */
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/disks")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(ParseDisks.class)
+ @Fallback(EmptyIterableWithMarkerOnNotFoundOr404.class)
+ ListenableFuture> listAtMarker(@QueryParam("pageToken") @Nullable String marker, ListOptions options);
+
+ /**
+ * @see DiskApi#list(org.jclouds.googlecompute.options.ListOptions)
+ */
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/disks")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(ParseDisks.class)
+ @Transform(ParseDisks.ToPagedIterable.class)
+ @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+ ListenableFuture extends PagedIterable> list();
+
+ /**
+ * @see DiskApi#list(org.jclouds.googlecompute.options.ListOptions)
+ */
+ @GET
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/disks")
+ @OAuthScopes(COMPUTE_READONLY_SCOPE)
+ @ResponseParser(ParseDisks.class)
+ @Transform(ParseDisks.ToPagedIterable.class)
+ @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+ ListenableFuture extends PagedIterable> list(ListOptions options);
+}
diff --git a/labs/google-compute/src/main/java/org/jclouds/googlecompute/functions/internal/ParseDisks.java b/labs/google-compute/src/main/java/org/jclouds/googlecompute/functions/internal/ParseDisks.java
new file mode 100644
index 0000000000..5973ebbb5a
--- /dev/null
+++ b/labs/google-compute/src/main/java/org/jclouds/googlecompute/functions/internal/ParseDisks.java
@@ -0,0 +1,70 @@
+/*
+ * 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.googlecompute.functions.internal;
+
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.googlecompute.GoogleComputeApi;
+import org.jclouds.googlecompute.domain.Disk;
+import org.jclouds.googlecompute.domain.ListPage;
+import org.jclouds.googlecompute.options.ListOptions;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * @author David Alves
+ */
+@Singleton
+public class ParseDisks extends ParseJson> {
+
+ @Inject
+ public ParseDisks(Json json) {
+ super(json, new TypeLiteral>() {});
+ }
+
+ public static class ToPagedIterable extends BaseToPagedIterable {
+
+ private final GoogleComputeApi api;
+
+ @Inject
+ protected ToPagedIterable(GoogleComputeApi api) {
+ this.api = checkNotNull(api, "api");
+ }
+
+ @Override
+ protected Function