diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Address.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Address.java
index b30293fb6d48..e1e70def80d5 100644
--- a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Address.java
+++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Address.java
@@ -172,8 +172,8 @@ public final int hashCode() {
return Objects.hash(super.hashCode(), options);
}
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- in.defaultReadObject();
+ private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {
+ input.defaultReadObject();
this.compute = options.service();
}
diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java
index 815b5ebe49e6..6d033688d8c2 100644
--- a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java
+++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java
@@ -582,7 +582,7 @@ class DiskTypeFilter extends ListFilter {
private static final long serialVersionUID = 4847837203592234453L;
- DiskTypeFilter(DiskTypeField field, ComparisonOperator operator, Object value) {
+ private DiskTypeFilter(DiskTypeField field, ComparisonOperator operator, Object value) {
super(field.selector(), operator, value);
}
@@ -630,7 +630,7 @@ class MachineTypeFilter extends ListFilter {
private static final long serialVersionUID = 7346062041571853235L;
- MachineTypeFilter(MachineTypeField field, ComparisonOperator operator, Object value) {
+ private MachineTypeFilter(MachineTypeField field, ComparisonOperator operator, Object value) {
super(field.selector(), operator, value);
}
@@ -678,7 +678,7 @@ class RegionFilter extends ListFilter {
private static final long serialVersionUID = 4464892812442567172L;
- RegionFilter(RegionField field, ComparisonOperator operator, Object value) {
+ private RegionFilter(RegionField field, ComparisonOperator operator, Object value) {
super(field.selector(), operator, value);
}
@@ -712,7 +712,7 @@ class ZoneFilter extends ListFilter {
private static final long serialVersionUID = -3927428278548808737L;
- ZoneFilter(ZoneField field, ComparisonOperator operator, Object value) {
+ private ZoneFilter(ZoneField field, ComparisonOperator operator, Object value) {
super(field.selector(), operator, value);
}
@@ -746,7 +746,7 @@ class OperationFilter extends ListFilter {
private static final long serialVersionUID = -3202249202748346427L;
- OperationFilter(OperationField field, ComparisonOperator operator, Object value) {
+ private OperationFilter(OperationField field, ComparisonOperator operator, Object value) {
super(field.selector(), operator, value);
}
@@ -794,7 +794,7 @@ class AddressFilter extends ListFilter {
private static final long serialVersionUID = -227481644259653765L;
- AddressFilter(AddressField field, ComparisonOperator operator, Object value) {
+ private AddressFilter(AddressField field, ComparisonOperator operator, Object value) {
super(field.selector(), operator, value);
}
@@ -821,6 +821,54 @@ public static AddressFilter notEquals(AddressField field, String value) {
}
}
+ /**
+ * Class for filtering snapshot lists.
+ */
+ class SnapshotFilter extends ListFilter {
+
+ private static final long serialVersionUID = 8757711630092406747L;
+
+ private SnapshotFilter(SnapshotField field, ComparisonOperator operator, Object value) {
+ super(field.selector(), operator, value);
+ }
+
+ /**
+ * Returns an equals filter for the given field and string value. For string fields,
+ * {@code value} is interpreted as a regular expression using RE2 syntax. {@code value} must
+ * match the entire field.
+ *
+ * @see RE2
+ */
+ public static SnapshotFilter equals(SnapshotField field, String value) {
+ return new SnapshotFilter(checkNotNull(field), ComparisonOperator.EQ, checkNotNull(value));
+ }
+
+ /**
+ * Returns a not-equals filter for the given field and string value. For string fields,
+ * {@code value} is interpreted as a regular expression using RE2 syntax. {@code value} must
+ * match the entire field.
+ *
+ * @see RE2
+ */
+ public static SnapshotFilter notEquals(SnapshotField field, String value) {
+ return new SnapshotFilter(checkNotNull(field), ComparisonOperator.NE, checkNotNull(value));
+ }
+
+ /**
+ * Returns an equals filter for the given field and long value.
+ */
+ public static SnapshotFilter equals(SnapshotField field, long value) {
+ return new SnapshotFilter(checkNotNull(field), ComparisonOperator.EQ, value);
+ }
+
+ /**
+ * Returns a not-equals filter for the given field and long value.
+ */
+ public static SnapshotFilter notEquals(SnapshotField field, long value) {
+ return new SnapshotFilter(checkNotNull(field), ComparisonOperator.NE, value);
+ }
+ }
+
/**
* Class for specifying disk type get options.
*/
@@ -863,6 +911,7 @@ public static DiskTypeListOption filter(DiskTypeFilter filter) {
/**
* Returns an option to specify the maximum number of disk types returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static DiskTypeListOption pageSize(long pageSize) {
return new DiskTypeListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -908,6 +957,7 @@ public static DiskTypeAggregatedListOption filter(DiskTypeFilter filter) {
/**
* Returns an option to specify the maximum number of disk types returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static DiskTypeAggregatedListOption pageSize(long pageSize) {
return new DiskTypeAggregatedListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -963,6 +1013,7 @@ public static MachineTypeListOption filter(MachineTypeFilter filter) {
/**
* Returns an option to specify the maximum number of machine types returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static MachineTypeListOption pageSize(long pageSize) {
return new MachineTypeListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -1008,6 +1059,7 @@ public static MachineTypeAggregatedListOption filter(MachineTypeFilter filter) {
/**
* Returns an option to specify the maximum number of machine types returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static MachineTypeAggregatedListOption pageSize(long pageSize) {
return new MachineTypeAggregatedListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -1063,6 +1115,7 @@ public static RegionListOption filter(RegionFilter filter) {
/**
* Returns an option to specify the maximum number of regions returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static RegionListOption pageSize(long pageSize) {
return new RegionListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -1130,6 +1183,7 @@ public static ZoneListOption filter(ZoneFilter filter) {
/**
* Returns an option to specify the maximum number of zones returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static ZoneListOption pageSize(long pageSize) {
return new ZoneListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -1219,6 +1273,7 @@ public static OperationListOption filter(OperationFilter filter) {
/**
* Returns an option to specify the maximum number of operations returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static OperationListOption pageSize(long pageSize) {
return new OperationListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -1286,6 +1341,7 @@ public static AddressListOption filter(AddressFilter filter) {
/**
* Returns an option to specify the maximum number of addresses returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static AddressListOption pageSize(long pageSize) {
return new AddressListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -1331,6 +1387,7 @@ public static AddressAggregatedListOption filter(AddressFilter filter) {
/**
* Returns an option to specify the maximum number of addresses returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
*/
public static AddressAggregatedListOption pageSize(long pageSize) {
return new AddressAggregatedListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
@@ -1344,6 +1401,74 @@ public static AddressAggregatedListOption pageToken(String pageToken) {
}
}
+ /**
+ * Class for specifying snapshot get options.
+ */
+ class SnapshotOption extends Option {
+
+ private static final long serialVersionUID = -3505179459035500945L;
+
+ private SnapshotOption(ComputeRpc.Option option, Object value) {
+ super(option, value);
+ }
+
+ /**
+ * Returns an option to specify the snapshot's fields to be returned by the RPC call. If this
+ * option is not provided, all the snapshot's fields are returned. {@code SnapshotOption.fields}
+ * can be used to specify only the fields of interest. {@link Snapshot#snapshotId()} is always
+ * returned, even if not specified.
+ */
+ public static SnapshotOption fields(SnapshotField... fields) {
+ return new SnapshotOption(ComputeRpc.Option.FIELDS, SnapshotField.selector(fields));
+ }
+ }
+
+ /**
+ * Class for specifying snapshot list options.
+ */
+ class SnapshotListOption extends Option {
+
+ private static final long serialVersionUID = 8278588147660831257L;
+
+ private SnapshotListOption(ComputeRpc.Option option, Object value) {
+ super(option, value);
+ }
+
+ /**
+ * Returns an option to specify a filter on the snapshots being listed.
+ */
+ public static SnapshotListOption filter(SnapshotFilter filter) {
+ return new SnapshotListOption(ComputeRpc.Option.FILTER, filter.toPb());
+ }
+
+ /**
+ * Returns an option to specify the maximum number of snapshots returned per page.
+ * {@code pageSize} must be between 0 and 500 (inclusive). If not specified 500 is used.
+ */
+ public static SnapshotListOption pageSize(long pageSize) {
+ return new SnapshotListOption(ComputeRpc.Option.MAX_RESULTS, pageSize);
+ }
+
+ /**
+ * Returns an option to specify the page token from which to start listing snapshots.
+ */
+ public static SnapshotListOption pageToken(String pageToken) {
+ return new SnapshotListOption(ComputeRpc.Option.PAGE_TOKEN, pageToken);
+ }
+
+ /**
+ * Returns an option to specify the snapshot's fields to be returned by the RPC call. If this
+ * option is not provided, all the snapshot's fields are returned.
+ * {@code SnapshotListOption.fields} can be used to specify only the fields of interest.
+ * {@link Snapshot#snapshotId()} is always returned, even if not specified.
+ */
+ public static SnapshotListOption fields(SnapshotField... fields) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("items(").append(SnapshotField.selector(fields)).append("),nextPageToken");
+ return new SnapshotListOption(ComputeRpc.Option.FIELDS, builder.toString());
+ }
+ }
+
/**
* Returns the requested disk type or {@code null} if not found.
*
@@ -1366,7 +1491,7 @@ public static AddressAggregatedListOption pageToken(String pageToken) {
Page listDiskTypes(String zone, DiskTypeListOption... options);
/**
- * Lists all disk types.
+ * Lists the disk types in all zones.
*
* @throws ComputeException upon failure
*/
@@ -1394,7 +1519,7 @@ public static AddressAggregatedListOption pageToken(String pageToken) {
Page listMachineTypes(String zone, MachineTypeListOption... options);
/**
- * Lists all machine types.
+ * Lists the machine types in all zones.
*
* @throws ComputeException upon failure
*/
@@ -1511,7 +1636,7 @@ public static AddressAggregatedListOption pageToken(String pageToken) {
Page listRegionAddresses(String region, AddressListOption... options);
/**
- * Lists all addresses.
+ * Lists both global and region addresses.
*
* @throws ComputeException upon failure
*/
@@ -1525,4 +1650,53 @@ public static AddressAggregatedListOption pageToken(String pageToken) {
* @throws ComputeException upon failure
*/
Operation delete(AddressId addressId, OperationOption... options);
+
+ /**
+ * Creates a new snapshot.
+ *
+ * @return a zone operation if the create request was issued correctly, {@code null} if
+ * {@code snapshot.sourceDisk} was not found
+ * @throws ComputeException upon failure
+ */
+ Operation create(SnapshotInfo snapshot, OperationOption... options);
+
+ /**
+ * Returns the requested snapshot or {@code null} if not found.
+ *
+ * @throws ComputeException upon failure
+ */
+ Snapshot getSnapshot(String snapshot, SnapshotOption... options);
+
+ /**
+ * Lists snapshots.
+ *
+ * @throws ComputeException upon failure
+ */
+ Page listSnapshots(SnapshotListOption... options);
+
+ /**
+ * Deletes the requested snapshot. Keep in mind that deleting a single snapshot might not
+ * necessarily delete all the data for that snapshot. If any data for the snapshot that is marked
+ * for deletion is needed for subsequent snapshots, the data will be moved to the next snapshot.
+ *
+ * @return a global operation if the request was issued correctly, {@code null} if the snapshot
+ * was not found
+ * @throws ComputeException upon failure
+ * @see
+ * Deleting a snapshot
+ */
+ Operation deleteSnapshot(SnapshotId snapshot, OperationOption... options);
+
+ /**
+ * Deletes the requested snapshot. Keep in mind that deleting a single snapshot might not
+ * necessarily delete all the data for that snapshot. If any data on the snapshot that is marked
+ * for deletion is needed for subsequent snapshots, the data will be moved to the next snapshot.
+ *
+ * @return a global operation if the request was issued correctly, {@code null} if the snapshot
+ * was not found
+ * @throws ComputeException upon failure
+ * @see
+ * Deleting a snapshot
+ */
+ Operation deleteSnapshot(String snapshot, OperationOption... options);
}
diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ComputeImpl.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ComputeImpl.java
index 838816a035e0..a348e1e0e253 100644
--- a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ComputeImpl.java
+++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/ComputeImpl.java
@@ -273,6 +273,25 @@ public Page nextPage() {
}
}
+ private static class SnapshotPageFetcher implements NextPageFetcher {
+
+ private static final long serialVersionUID = 6205774609802216986L;
+ private final Map requestOptions;
+ private final ComputeOptions serviceOptions;
+
+ SnapshotPageFetcher(ComputeOptions serviceOptions, String cursor,
+ Map optionMap) {
+ this.requestOptions =
+ PageImpl.nextRequestOptions(ComputeRpc.Option.PAGE_TOKEN, cursor, optionMap);
+ this.serviceOptions = serviceOptions;
+ }
+
+ @Override
+ public Page nextPage() {
+ return listSnapshots(serviceOptions, requestOptions);
+ }
+ }
+
private final ComputeRpc computeRpc;
ComputeImpl(ComputeOptions options) {
@@ -881,8 +900,8 @@ public Address apply(com.google.api.services.compute.model.Address address) {
return Address.fromPb(serviceOptions.service(), address);
}
});
- return new PageImpl<>(new AggregatedAddressPageFetcher(serviceOptions, cursor,
- optionsMap), cursor, operations);
+ return new PageImpl<>(new AggregatedAddressPageFetcher(serviceOptions, cursor, optionsMap),
+ cursor, operations);
} catch (RetryHelper.RetryHelperException e) {
throw ComputeException.translateAndThrow(e);
}
@@ -914,6 +933,99 @@ public com.google.api.services.compute.model.Operation call() {
}
}
+ @Override
+ public Operation create(SnapshotInfo snapshot, OperationOption... options) {
+ final SnapshotInfo completeSnapshot = snapshot.setProjectId(options().projectId());
+ final Map optionsMap = optionMap(options);
+ try {
+ com.google.api.services.compute.model.Operation answer =
+ runWithRetries(new Callable() {
+ @Override
+ public com.google.api.services.compute.model.Operation call() {
+ return computeRpc.createSnapshot(completeSnapshot.sourceDisk().zone(),
+ completeSnapshot.sourceDisk().disk(), completeSnapshot.snapshotId().snapshot(),
+ completeSnapshot.description(), optionsMap);
+ }
+ }, options().retryParams(), EXCEPTION_HANDLER);
+ return answer == null ? null : Operation.fromPb(this, answer);
+ } catch (RetryHelper.RetryHelperException e) {
+ throw ComputeException.translateAndThrow(e);
+ }
+ }
+
+ @Override
+ public Snapshot getSnapshot(final String snapshot, SnapshotOption... options) {
+ final Map optionsMap = optionMap(options);
+ try {
+ com.google.api.services.compute.model.Snapshot answer =
+ runWithRetries(new Callable() {
+ @Override
+ public com.google.api.services.compute.model.Snapshot call() {
+ return computeRpc.getSnapshot(snapshot, optionsMap);
+ }
+ }, options().retryParams(), EXCEPTION_HANDLER);
+ return answer == null ? null : Snapshot.fromPb(this, answer);
+ } catch (RetryHelper.RetryHelperException e) {
+ throw ComputeException.translateAndThrow(e);
+ }
+ }
+
+ @Override
+ public Page listSnapshots(SnapshotListOption... options) {
+ return listSnapshots(options(), optionMap(options));
+ }
+
+ private static Page listSnapshots(final ComputeOptions serviceOptions,
+ final Map optionsMap) {
+ try {
+ ComputeRpc.Tuple> result =
+ runWithRetries(new Callable>>() {
+ @Override
+ public ComputeRpc.Tuple> call() {
+ return serviceOptions.rpc().listSnapshots(optionsMap);
+ }
+ }, serviceOptions.retryParams(), EXCEPTION_HANDLER);
+ String cursor = result.x();
+ Iterable snapshots = Iterables.transform(
+ result.y() == null ? ImmutableList.of()
+ : result.y(),
+ new Function() {
+ @Override
+ public Snapshot apply(com.google.api.services.compute.model.Snapshot snapshot) {
+ return Snapshot.fromPb(serviceOptions.service(), snapshot);
+ }
+ });
+ return new PageImpl<>(new SnapshotPageFetcher(serviceOptions, cursor, optionsMap), cursor,
+ snapshots);
+ } catch (RetryHelper.RetryHelperException e) {
+ throw ComputeException.translateAndThrow(e);
+ }
+ }
+
+ @Override
+ public Operation deleteSnapshot(SnapshotId snapshot, OperationOption... options) {
+ return deleteSnapshot(snapshot.snapshot(), options);
+ }
+
+ @Override
+ public Operation deleteSnapshot(final String snapshot, OperationOption... options) {
+ final Map optionsMap = optionMap(options);
+ try {
+ com.google.api.services.compute.model.Operation answer =
+ runWithRetries(new Callable() {
+ @Override
+ public com.google.api.services.compute.model.Operation call() {
+ return computeRpc.deleteSnapshot(snapshot, optionsMap);
+ }
+ }, options().retryParams(), EXCEPTION_HANDLER);
+ return answer == null ? null : Operation.fromPb(this, answer);
+ } catch (RetryHelper.RetryHelperException e) {
+ throw ComputeException.translateAndThrow(e);
+ }
+ }
+
private Map optionMap(Option... options) {
Map optionMap = Maps.newEnumMap(ComputeRpc.Option.class);
for (Option option : options) {
diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Operation.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Operation.java
index ce519edc970d..78afc170f671 100644
--- a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Operation.java
+++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Operation.java
@@ -792,8 +792,8 @@ com.google.api.services.compute.model.Operation toPb() {
return operationPb;
}
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- in.defaultReadObject();
+ private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {
+ input.defaultReadObject();
this.compute = options.service();
}
diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Snapshot.java b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Snapshot.java
new file mode 100644
index 000000000000..e93a419d5b4a
--- /dev/null
+++ b/gcloud-java-compute/src/main/java/com/google/gcloud/compute/Snapshot.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 com.google.gcloud.compute;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.gcloud.compute.Compute.OperationOption;
+import com.google.gcloud.compute.Compute.SnapshotOption;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A Google Compute Engine snapshot. Compute Engine allows you to take snapshots of your persistent
+ * disk and create new persistent disks from that snapshot. This can be useful for backing up data,
+ * recreating a persistent disk that might have been lost, or copying a persistent disk. Snapshots
+ * can be applied across persistent disk types. {@code Snapshot} adds a layer of service-related
+ * functionality over {@link SnapshotInfo}. Objects of this class are immutable; to get a
+ * {@code Snapshot} object with the most recent information use {@link #reload}.
+ *
+ * @see Use
+ * persistent disk snapshots
+ */
+public class Snapshot extends SnapshotInfo {
+
+ private static final long serialVersionUID = -973924811396336695L;
+
+ private final ComputeOptions options;
+ private transient Compute compute;
+
+ /**
+ * A builder for {@code Snapshot} objects.
+ */
+ public static class Builder extends SnapshotInfo.Builder {
+
+ private final Compute compute;
+ private final SnapshotInfo.BuilderImpl infoBuilder;
+
+ Builder(Compute compute, SnapshotId snapshotId, DiskId sourceDisk) {
+ this.compute = compute;
+ this.infoBuilder = new SnapshotInfo.BuilderImpl();
+ this.infoBuilder.snapshotId(snapshotId);
+ this.infoBuilder.sourceDisk(sourceDisk);
+ }
+
+ Builder(Snapshot snapshot) {
+ this.compute = snapshot.compute;
+ this.infoBuilder = new SnapshotInfo.BuilderImpl(snapshot);
+ }
+
+ @Override
+ Builder id(String id) {
+ infoBuilder.id(id);
+ return this;
+ }
+
+ @Override
+ Builder creationTimestamp(Long creationTimestamp) {
+ infoBuilder.creationTimestamp(creationTimestamp);
+ return this;
+ }
+
+ @Override
+ public Builder snapshotId(SnapshotId snapshotId) {
+ infoBuilder.snapshotId(snapshotId);
+ return this;
+ }
+
+ @Override
+ public Builder description(String description) {
+ infoBuilder.description(description);
+ return this;
+ }
+
+ @Override
+ Builder status(Status status) {
+ infoBuilder.status(status);
+ return this;
+ }
+
+ @Override
+ Builder diskSizeGb(Long diskSizeGb) {
+ infoBuilder.diskSizeGb(diskSizeGb);
+ return this;
+ }
+
+ @Override
+ Builder licenses(List licenses) {
+ infoBuilder.licenses(licenses);
+ return this;
+ }
+
+ @Override
+ public Builder sourceDisk(DiskId sourceDisk) {
+ infoBuilder.sourceDisk(sourceDisk);
+ return this;
+ }
+
+ @Override
+ Builder sourceDiskId(String sourceDiskId) {
+ infoBuilder.sourceDiskId(sourceDiskId);
+ return this;
+ }
+
+ @Override
+ Builder storageBytes(Long storageBytes) {
+ infoBuilder.storageBytes(storageBytes);
+ return this;
+ }
+
+ @Override
+ Builder storageBytesStatus(StorageBytesStatus storageBytesStatus) {
+ infoBuilder.storageBytesStatus(storageBytesStatus);
+ return this;
+ }
+
+ @Override
+ public Snapshot build() {
+ return new Snapshot(compute, infoBuilder);
+ }
+ }
+
+ Snapshot(Compute compute, SnapshotInfo.BuilderImpl infoBuilder) {
+ super(infoBuilder);
+ this.compute = checkNotNull(compute);
+ this.options = compute.options();
+ }
+
+ /**
+ * Checks if this snapshot exists.
+ *
+ * @return {@code true} if this snapshot exists, {@code false} otherwise
+ * @throws ComputeException upon failure
+ */
+ public boolean exists() {
+ return reload(SnapshotOption.fields()) != null;
+ }
+
+ /**
+ * Fetches current snapshot's latest information. Returns {@code null} if the snapshot does not
+ * exist.
+ *
+ * @param options snapshot options
+ * @return a {@code Snapshot} object with latest information or {@code null} if not found
+ * @throws ComputeException upon failure
+ */
+ public Snapshot reload(SnapshotOption... options) {
+ return compute.getSnapshot(snapshotId().snapshot(), options);
+ }
+
+ /**
+ * Deletes this snapshot.
+ *
+ * @return a global operation if delete request was successfully sent, {@code null} if the
+ * snapshot was not found
+ * @throws ComputeException upon failure
+ */
+ public Operation delete(OperationOption... options) {
+ return compute.deleteSnapshot(snapshotId(), options);
+ }
+
+ /**
+ * Returns the snapshot's {@code Compute} object used to issue requests.
+ */
+ public Compute compute() {
+ return compute;
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder(this);
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ return obj instanceof Snapshot
+ && Objects.equals(toPb(), ((Snapshot) obj).toPb())
+ && Objects.equals(options, ((Snapshot) obj).options);
+ }
+
+ @Override
+ public final int hashCode() {
+ return Objects.hash(super.hashCode(), options);
+ }
+
+ private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException {
+ input.defaultReadObject();
+ this.compute = options.service();
+ }
+
+ static Snapshot fromPb(Compute compute,
+ com.google.api.services.compute.model.Snapshot snapshotPb) {
+ return new Snapshot(compute, new SnapshotInfo.BuilderImpl(snapshotPb));
+ }
+}
diff --git a/gcloud-java-compute/src/main/java/com/google/gcloud/spi/ComputeRpc.java b/gcloud-java-compute/src/main/java/com/google/gcloud/spi/ComputeRpc.java
index 66152f5464a4..ff0831ece6e9 100644
--- a/gcloud-java-compute/src/main/java/com/google/gcloud/spi/ComputeRpc.java
+++ b/gcloud-java-compute/src/main/java/com/google/gcloud/spi/ComputeRpc.java
@@ -22,6 +22,7 @@
import com.google.api.services.compute.model.MachineType;
import com.google.api.services.compute.model.Operation;
import com.google.api.services.compute.model.Region;
+import com.google.api.services.compute.model.Snapshot;
import com.google.api.services.compute.model.Zone;
import com.google.gcloud.compute.ComputeException;
@@ -255,8 +256,8 @@ public Y y() {
/**
* Deletes the requested global address.
*
- * @return a global operation if request was issued correctly, {@code null} if the address was not
- * found
+ * @return a global operation if the request was issued correctly, {@code null} if the address was
+ * not found
* @throws ComputeException upon failure
*/
Operation deleteGlobalAddress(String address, Map