Skip to content

Commit

Permalink
Add whenDone method and CompletionCallback to Compute Operation
Browse files Browse the repository at this point in the history
  • Loading branch information
mziccard committed May 19, 2016
1 parent f3cd884 commit e29f635
Show file tree
Hide file tree
Showing 9 changed files with 378 additions and 333 deletions.
35 changes: 23 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,22 +202,31 @@ import com.google.cloud.compute.Compute;
import com.google.cloud.compute.ComputeOptions;
import com.google.cloud.compute.Disk;
import com.google.cloud.compute.DiskId;
import com.google.cloud.compute.Operation;
import com.google.cloud.compute.Operation.OperationError;
import com.google.cloud.compute.Operation.OperationWarning;
import com.google.cloud.compute.Snapshot;
Compute compute = ComputeOptions.defaultInstance().service();
import java.util.List;
final Compute compute = ComputeOptions.defaultInstance().service();
DiskId diskId = DiskId.of("us-central1-a", "disk-name");
Disk disk = compute.getDisk(diskId, Compute.DiskOption.fields());
if (disk != null) {
String snapshotName = "disk-name-snapshot";
final String snapshotName = "disk-name-snapshot";
Operation operation = disk.createSnapshot(snapshotName);
while (!operation.isDone()) {
Thread.sleep(1000L);
}
if (operation.errors() == null) {
// use snapshot
Snapshot snapshot = compute.getSnapshot("disk-name-snapshot");
}
operation.whenDone(new Operation.CompletionCallback() {
@Override
public void success(Operation operation) {
// use snapshot
Snapshot snapshot = compute.getSnapshot(snapshotName);
}
@Override
public void error(List<OperationError> errors, List<OperationWarning> warnings) {
// inspect errors
throw new RuntimeException("Snaphsot creation failed");
}
});
}
```
The second snippet shows how to create a virtual machine instance. Complete source code can be found
Expand All @@ -233,8 +242,10 @@ import com.google.cloud.compute.InstanceId;
import com.google.cloud.compute.InstanceInfo;
import com.google.cloud.compute.MachineTypeId;
import com.google.cloud.compute.NetworkId;
import com.google.cloud.compute.NetworkInterface;
import com.google.cloud.compute.Operation;
import com.google.cloud.compute.Operation.OperationError;
import com.google.cloud.compute.Operation.OperationWarning;
import java.util.List;
Compute compute = ComputeOptions.defaultInstance().service();
ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329");
Expand Down
77 changes: 44 additions & 33 deletions gcloud-java-compute/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,26 +104,33 @@ Add the following imports at the top of your file:
```java
import com.google.cloud.compute.AddressInfo;
import com.google.cloud.compute.Operation;
import com.google.cloud.compute.Operation.OperationError;
import com.google.cloud.compute.Operation.OperationWarning;
import com.google.cloud.compute.RegionAddressId;

import java.util.List;
```

Then add the following code to create an address. Most Compute Engine calls return an `Operation`
object that can be used to wait for operation completion and to check whether operation failed or
succeeded:

```java
RegionAddressId addressId = RegionAddressId.of("us-central1", "test-address");
final RegionAddressId addressId = RegionAddressId.of("us-central1", "test-address");
Operation operation = compute.create(AddressInfo.of(addressId));
while (!operation.isDone()) {
Thread.sleep(1000L);
}
operation = operation.reload();
if (operation.errors() == null) {
System.out.println("Address " + addressId + " was successfully created");
} else {
// inspect operation.errors()
throw new RuntimeException("Address creation failed");
}
// Wait for operation to complete
operation.whenDone(new Operation.CompletionCallback() {
@Override
public void success(Operation operation) {
System.out.println("Address " + addressId + " was successfully created");
}

@Override
public void error(List<OperationError> errors, List<OperationWarning> warnings) {
// inspect errors
throw new RuntimeException("Address creation failed");
}
});
```

#### Creating a persistent disk
Expand All @@ -145,21 +152,23 @@ import com.google.cloud.compute.ImageId;
Then add the following code to create a disk and wait for disk creation to terminate.

```java
ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329");
final ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329");
DiskId diskId = DiskId.of("us-central1-a", "test-disk");
ImageDiskConfiguration diskConfiguration = ImageDiskConfiguration.of(imageId);
DiskInfo disk = DiskInfo.of(diskId, diskConfiguration);
Operation operation = compute.create(disk);
while (!operation.isDone()) {
Thread.sleep(1000L);
}
operation = operation.reload();
if (operation.errors() == null) {
System.out.println("Disk " + diskId + " was successfully created");
} else {
// inspect operation.errors()
throw new RuntimeException("Disk creation failed");
}
operation.whenDone(new Operation.CompletionCallback() {
@Override
public void success(Operation operation) {
System.out.println("Disk " + diskId + " was successfully created");
}

@Override
public void error(List<OperationError> errors, List<OperationWarning> warnings) {
// inspect errors
throw new RuntimeException("Disk creation failed");
}
});
```

#### Creating a virtual machine instance
Expand All @@ -186,7 +195,7 @@ Then add the following code to create an instance and wait for instance creation

```java
Address externalIp = compute.getAddress(addressId);
InstanceId instanceId = InstanceId.of("us-central1-a", "test-instance");
final InstanceId instanceId = InstanceId.of("us-central1-a", "test-instance");
NetworkId networkId = NetworkId.of("default");
PersistentDiskConfiguration attachConfiguration =
PersistentDiskConfiguration.builder(diskId).boot(true).build();
Expand All @@ -198,16 +207,18 @@ MachineTypeId machineTypeId = MachineTypeId.of("us-central1-a", "n1-standard-1")
InstanceInfo instance =
InstanceInfo.of(instanceId, machineTypeId, attachedDisk, networkInterface);
Operation operation = compute.create(instance);
while (!operation.isDone()) {
Thread.sleep(1000L);
}
operation = operation.reload();
if (operation.errors() == null) {
System.out.println("Instance " + instanceId + " was successfully created");
} else {
// inspect operation.errors()
throw new RuntimeException("Instance creation failed");
}
operation.whenDone(new Operation.CompletionCallback() {
@Override
public void success(Operation operation) {
System.out.println("Instance " + instanceId + " was successfully created");
}

@Override
public void error(List<OperationError> errors, List<OperationWarning> warnings) {
// inspect errors
throw new RuntimeException("Instance creation failed");
}
});
```

#### Complete source code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
* {@link #operationId()} returns {@link GlobalOperationId} for global operations,
* {@link RegionOperationId} for region operations, and {@link ZoneOperationId} for zone operations.
* To get an {@code Operation} object with the most recent information, use
* {@link #reload(OperationOption...)}.
* {@link #reload(Compute.OperationOption...)}.
*/
public class Operation implements Serializable {

Expand Down Expand Up @@ -292,6 +292,24 @@ public int hashCode() {
}
}

/**
* A callback for operation completion.
*/
public interface CompletionCallback {
/**
* The method called when the operation completes successfully.
*/
void success(Operation operation);

/**
* The method called when the operation completes with errors. {@code errors} contains all
* errors encountered while processing this operation (see {@link Operation#errors()}).
* {@code warnings} contains all warnings encountered while processing this operation (see
* {@link Operation#warnings()}).
*/
void error(List<OperationError> errors, List<OperationWarning> warnings);
}

static final class Builder {

private Compute compute;
Expand Down Expand Up @@ -635,7 +653,7 @@ public String description() {
* @return {@code true} if this operation exists, {@code false} otherwise
* @throws ComputeException upon failure
*/
public boolean exists() throws ComputeException {
public boolean exists() {
return reload(OperationOption.fields()) != null;
}

Expand All @@ -652,12 +670,49 @@ public boolean exists() throws ComputeException {
* not exist, {@code false} if the state is not {@link Operation.Status#DONE}
* @throws ComputeException upon failure
*/
public boolean isDone() throws ComputeException {
public boolean isDone() {
Operation operation = compute.getOperation(operationId,
OperationOption.fields(Compute.OperationField.STATUS));
return operation == null || operation.status() == Status.DONE;
}

/**
* Waits until this operation completes its execution, either failing or succeeding. If the
* operation does not exist, this method returns without executing any method of the provided
* callback. If the operation completed successfully the
* {@link CompletionCallback#success(Operation)} method is called. If the operation completed with
* errors the {@link CompletionCallback#error(List, List)} method is called.
* <pre> {@code
* operation.whenDone(new CompletionCallback() {
* void success(Operation operation) {
* // completed successfully
* }
*
* void error(List<OperationError> errors, List<OperationWarning> warnings) {
* // handle error
* }
* });}</pre>
*
* @throws ComputeException upon failure
* @throws InterruptedException if the current thread gets interrupted while waiting for the
* operation to complete
*/
public void whenDone(CompletionCallback callback) throws InterruptedException {
while (!isDone()) {
Thread.sleep(500L);
}
Operation updatedOperation = reload();
if (updatedOperation == null) {
return;
}
List<OperationError> errors = updatedOperation.errors();
if (errors != null) {
callback.error(errors, updatedOperation.warnings());
} else {
callback.success(updatedOperation);
}
}

/**
* Fetches current operation's latest information. Returns {@code null} if the operation does not
* exist.
Expand All @@ -666,7 +721,7 @@ public boolean isDone() throws ComputeException {
* @return an {@code Operation} object with latest information or {@code null} if not found
* @throws ComputeException upon failure
*/
public Operation reload(OperationOption... options) throws ComputeException {
public Operation reload(OperationOption... options) {
return compute.getOperation(operationId, options);
}

Expand All @@ -677,7 +732,7 @@ public Operation reload(OperationOption... options) throws ComputeException {
* @return {@code true} if operation was deleted, {@code false} if it was not found
* @throws ComputeException upon failure
*/
public boolean delete() throws ComputeException {
public boolean delete() {
return compute.deleteOperation(operationId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,49 @@
* <a href="https://github.com/GoogleCloudPlatform/gcloud-java/tree/master/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateSnapshot.java">
* CreateSnapshot.java</a>.
* <pre> {@code
* Compute compute = ComputeOptions.defaultInstance().service();
* final Compute compute = ComputeOptions.defaultInstance().service();
* DiskId diskId = DiskId.of("us-central1-a", "disk-name");
* Disk disk = compute.getDisk(diskId, Compute.DiskOption.fields());
* if (disk != null) {
* String snapshotName = "disk-name-snapshot";
* final String snapshotName = "disk-name-snapshot";
* Operation operation = disk.createSnapshot(snapshotName);
* while (!operation.isDone()) {
* Thread.sleep(1000L);
* }
* if (operation.errors() == null) {
* // use snapshot
* Snapshot snapshot = compute.getSnapshot("disk-name-snapshot");
* }
* operation.whenDone(new Operation.CompletionCallback() {
* public void success(Operation operation) {
* // use snapshot
* Snapshot snapshot = compute.getSnapshot(snapshotName);
* }
*
* public void error(List<OperationError> errors, List<OperationWarning> warnings) {
* // inspect errors
* throw new RuntimeException("Snaphsot creation failed");
* }
* });
* }}</pre>
* <p>This second example shows how to create a virtual machine instance. Complete source code can
* be found at
* <a href="https://github.com/GoogleCloudPlatform/gcloud-java/tree/master/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateInstance.java">
* CreateInstance.java</a>.
* <pre> {@code
* Compute compute = ComputeOptions.defaultInstance().service();
* final Compute compute = ComputeOptions.defaultInstance().service();
* ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329");
* NetworkId networkId = NetworkId.of("default");
* AttachedDisk attachedDisk = AttachedDisk.of(AttachedDisk.CreateDiskConfiguration.of(imageId));
* NetworkInterface networkInterface = NetworkInterface.of(networkId);
* InstanceId instanceId = InstanceId.of("us-central1-a", "instance-name");
* final InstanceId instanceId = InstanceId.of("us-central1-a", "instance-name");
* MachineTypeId machineTypeId = MachineTypeId.of("us-central1-a", "n1-standard-1");
* Operation operation =
* compute.create(InstanceInfo.of(instanceId, machineTypeId, attachedDisk, networkInterface));
* while (!operation.isDone()) {
* Thread.sleep(1000L);
* }
* if (operation.errors() == null) {
* // use instance
* Instance instance = compute.getInstance(instanceId);
* }}</pre>
* operation.whenDone(new Operation.CompletionCallback() {
* public void success(Operation operation) {
* // use instance
* Instance instance = compute.getInstance(instanceId);
* }
*
* public void error(List<OperationError> errors, List<OperationWarning> warnings) {
* // inspect errors
* throw new RuntimeException("Instance creation failed");
* }
* });}</pre>
*
* @see <a href="https://cloud.google.com/compute/">Google Cloud Compute</a>
*/
Expand Down
Loading

0 comments on commit e29f635

Please sign in to comment.