From 8e31c56ea1c319b14562ef82fe69e46e4fe9570b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B5=D1=82=D1=8F=D0=BD=D0=B0=20=D0=AF=D0=B3=D0=BE?= =?UTF-8?q?=D0=B4=D1=81=D1=8C=D0=BA=D0=B0?= <49729677+TetyanaYahodska@users.noreply.github.com> Date: Fri, 27 Dec 2024 18:53:31 +0100 Subject: [PATCH 1/7] feat(compute): add compute disk create secondary sample. (#9643) * Implemented compute_disk_create_secondary sample, created test * Fixed code * Fixed variable * Fixed code * Merged changes from main * Fixed lint issue --- .../disks/CreateDiskSecondaryZonal.java | 92 +++++++++++++++++++ .../src/test/java/compute/disks/DisksIT.java | 37 ++++++-- 2 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 compute/cloud-client/src/main/java/compute/disks/CreateDiskSecondaryZonal.java diff --git a/compute/cloud-client/src/main/java/compute/disks/CreateDiskSecondaryZonal.java b/compute/cloud-client/src/main/java/compute/disks/CreateDiskSecondaryZonal.java new file mode 100644 index 00000000000..58135d4a3a3 --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/disks/CreateDiskSecondaryZonal.java @@ -0,0 +1,92 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.disks; + +// [START compute_disk_create_secondary] +import com.google.cloud.compute.v1.Disk; +import com.google.cloud.compute.v1.DiskAsyncReplication; +import com.google.cloud.compute.v1.DisksClient; +import com.google.cloud.compute.v1.Operation; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class CreateDiskSecondaryZonal { + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // The project that contains the primary disk. + String primaryProjectId = "PRIMARY_PROJECT_ID"; + // The project that contains the secondary disk. + String secondaryProjectId = "SECONDARY_PROJECT_ID"; + // Name of the primary disk you want to use. + String primaryDiskName = "PRIMARY_DISK_NAME"; + // Name of the zone in which your primary disk is located. + // Learn more about zones and regions: + // https://cloud.google.com/compute/docs/disks/async-pd/about#supported_region_pairs + String primaryDiskZone = "us-central1-a"; + // Name of the disk you want to create. + String secondaryDiskName = "SECONDARY_DISK_NAME"; + // Name of the zone in which you want to create the secondary disk. + String secondaryDiskZone = "us-east1-c"; + // Size of the new disk in gigabytes. + long diskSizeGb = 30L; + // The type of the disk you want to create. This value uses the following format: + // "projects/{projectId}/zones/{zone}/diskTypes/ + // (pd-standard|pd-ssd|pd-balanced|pd-extreme)". + String diskType = String.format( + "projects/%s/zones/%s/diskTypes/pd-balanced", secondaryProjectId, secondaryDiskZone); + + createDiskSecondaryZonal(primaryProjectId, secondaryProjectId, primaryDiskName, + secondaryDiskName, primaryDiskZone, secondaryDiskZone, diskSizeGb, diskType); + } + + // Creates a secondary disk in a specified zone. + public static Operation.Status createDiskSecondaryZonal(String primaryProjectId, + String secondaryProjectId, String primaryDiskName, String secondaryDiskName, + String primaryDiskZone, String secondaryDiskZone, long diskSizeGb, String diskType) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (DisksClient disksClient = DisksClient.create()) { + String primaryDiskSource = String.format("projects/%s/zones/%s/disks/%s", + primaryProjectId, primaryDiskZone, primaryDiskName); + + DiskAsyncReplication asyncReplication = DiskAsyncReplication.newBuilder() + .setDisk(primaryDiskSource) + .build(); + Disk disk = Disk.newBuilder() + .setName(secondaryDiskName) + .setZone(secondaryDiskZone) + .setSizeGb(diskSizeGb) + .setType(diskType) + .setAsyncPrimaryDisk(asyncReplication) + .build(); + + Operation response = disksClient.insertAsync(secondaryProjectId, secondaryDiskZone, disk) + .get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error creating secondary disks! " + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_disk_create_secondary] + diff --git a/compute/cloud-client/src/test/java/compute/disks/DisksIT.java b/compute/cloud-client/src/test/java/compute/disks/DisksIT.java index 20d888096cc..2e075d663e5 100644 --- a/compute/cloud-client/src/test/java/compute/disks/DisksIT.java +++ b/compute/cloud-client/src/test/java/compute/disks/DisksIT.java @@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertEquals; import com.google.cloud.compute.v1.AttachedDisk; import com.google.cloud.compute.v1.AttachedDiskInitializeParams; @@ -46,7 +47,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.junit.Assert; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -77,6 +77,7 @@ public class DisksIT { String.format("projects/%s/zones/%s-a", PROJECT_ID, REGION), String.format("projects/%s/zones/%s-b", PROJECT_ID, REGION)); private static String SECONDARY_REGIONAL_DISK; + private static String SECONDARY_DISK; private static final long DISK_SIZE = 10L; private ByteArrayOutputStream stdOut; @@ -107,14 +108,17 @@ public static void setup() REGIONAL_BLANK_DISK = "gcloud-test-disk-rattach-" + uuid; REGIONAL_REPLICATED_DISK = "gcloud-test-disk-replicated-" + uuid; SECONDARY_REGIONAL_DISK = "gcloud-test-disk-secondary-regional-" + uuid; + SECONDARY_DISK = "gcloud-test-disk-secondary-" + uuid; // Cleanup existing stale resources. Util.cleanUpExistingInstances("test-disks", PROJECT_ID, ZONE); Util.cleanUpExistingDisks("gcloud-test-", PROJECT_ID, ZONE); - Util.cleanUpExistingRegionalDisks("gcloud-test-disk-secondary-regional-", PROJECT_ID, REGION); - Util.cleanUpExistingRegionalDisks("gcloud-test-disk-rattach-", PROJECT_ID, REGION); - Util.cleanUpExistingSnapshots("gcloud-test-snapshot-", PROJECT_ID); + Util.cleanUpExistingDisks("gcloud-test-", PROJECT_ID, "us-central1-c"); + Util.cleanUpExistingRegionalDisks( + "gcloud-test-disk-secondary-regional-", PROJECT_ID, "us-central1"); Util.cleanUpExistingRegionalDisks("gcloud-test-disk-", PROJECT_ID, REGION); + Util.cleanUpExistingSnapshots("gcloud-test-snapshot-", PROJECT_ID); + // Create disk from image. Image debianImage = null; try (ImagesClient imagesClient = ImagesClient.create()) { @@ -181,6 +185,7 @@ public static void cleanUp() RegionalDelete.deleteRegionalDisk(PROJECT_ID, REGION, REGIONAL_BLANK_DISK); RegionalDelete.deleteRegionalDisk(PROJECT_ID, REGION, REGIONAL_REPLICATED_DISK); RegionalDelete.deleteRegionalDisk(PROJECT_ID, "us-central1", SECONDARY_REGIONAL_DISK); + DeleteDisk.deleteDisk(PROJECT_ID, "us-central1-c", SECONDARY_DISK); stdOut.close(); System.setOut(out); @@ -285,7 +290,7 @@ public void testDiskAttachResize() throws IOException, ExecutionException, InterruptedException, TimeoutException { // Test disk attach. Instance instance = Util.getInstance(PROJECT_ID, ZONE, INSTANCE_NAME); - Assert.assertEquals(1, instance.getDisksCount()); + assertEquals(1, instance.getDisksCount()); Disk zonalDisk = Util.getDisk(PROJECT_ID, ZONE, ZONAL_BLANK_DISK); Disk regionalDisk = Util.getRegionalDisk(PROJECT_ID, REGION, REGIONAL_BLANK_DISK); @@ -305,8 +310,8 @@ public void testDiskAttachResize() ResizeRegionalDisk.resizeRegionalDisk(PROJECT_ID, regionalDisk.getRegion().split("regions/")[1], regionalDisk.getName(), 23); - Assert.assertEquals(22, Util.getDisk(PROJECT_ID, ZONE, ZONAL_BLANK_DISK).getSizeGb()); - Assert.assertEquals(23, + assertEquals(22, Util.getDisk(PROJECT_ID, ZONE, ZONAL_BLANK_DISK).getSizeGb()); + assertEquals(23, Util.getRegionalDisk(PROJECT_ID, REGION, REGIONAL_BLANK_DISK).getSizeGb()); } @@ -315,8 +320,10 @@ public void testCreateReplicatedDisk() throws IOException, ExecutionException, InterruptedException, TimeoutException { Status status = CreateReplicatedDisk.createReplicatedDisk(PROJECT_ID, REGION, replicaZones, REGIONAL_REPLICATED_DISK, 100, DISK_TYPE); + Disk disk = Util.getRegionalDisk(PROJECT_ID, REGION, REGIONAL_REPLICATED_DISK); assertThat(status).isEqualTo(Status.DONE); + assertEquals(REGIONAL_REPLICATED_DISK, disk.getName()); } @Test @@ -327,7 +334,23 @@ public void testCreateDiskSecondaryRegional() Status status = CreateDiskSecondaryRegional.createDiskSecondaryRegional( PROJECT_ID, PROJECT_ID, REGIONAL_BLANK_DISK, SECONDARY_REGIONAL_DISK, REGION, "us-central1", DISK_SIZE, diskType); + Disk disk = Util.getRegionalDisk(PROJECT_ID, "us-central1", SECONDARY_REGIONAL_DISK); + + assertThat(status).isEqualTo(Status.DONE); + assertEquals(SECONDARY_REGIONAL_DISK, disk.getName()); + } + + @Test + public void testCreateDiskSecondaryZonal() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + String diskType = String.format( + "projects/%s/zones/%s/diskTypes/pd-ssd", PROJECT_ID, ZONE); + Status status = CreateDiskSecondaryZonal.createDiskSecondaryZonal( + PROJECT_ID, PROJECT_ID, EMPTY_DISK_NAME, SECONDARY_DISK, ZONE, + "us-central1-c", DISK_SIZE, diskType); + Disk disk = Util.getDisk(PROJECT_ID, "us-central1-c", SECONDARY_DISK); assertThat(status).isEqualTo(Status.DONE); + assertEquals(SECONDARY_DISK, disk.getName()); } } From ee8e513013a1d8140cefe8ca30fe51af8669a5d5 Mon Sep 17 00:00:00 2001 From: OremGLG Date: Sat, 28 Dec 2024 21:13:14 -0600 Subject: [PATCH 2/7] fix(storage): migrate old region all to storagetransfer_transfer_all step 1 (#9917) --- .../storagetransfer/samples/test/util/TransferJobUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage-transfer/src/test/java/com/google/cloud/storage/storagetransfer/samples/test/util/TransferJobUtils.java b/storage-transfer/src/test/java/com/google/cloud/storage/storagetransfer/samples/test/util/TransferJobUtils.java index c2fedcab472..af8b2044be9 100644 --- a/storage-transfer/src/test/java/com/google/cloud/storage/storagetransfer/samples/test/util/TransferJobUtils.java +++ b/storage-transfer/src/test/java/com/google/cloud/storage/storagetransfer/samples/test/util/TransferJobUtils.java @@ -14,6 +14,7 @@ * limitations under the License. */ +// [START storagetransfer_transfer_all] // [START all] package com.google.cloud.storage.storagetransfer.samples.test.util; @@ -68,3 +69,4 @@ public static TimeOfDay createTimeOfDay(String timeString) } } // [END all] +// [END storagetransfer_transfer_all] \ No newline at end of file From c917ab6d82e60a2706596e9e0e75b5cf54ff04d8 Mon Sep 17 00:00:00 2001 From: OremGLG Date: Sat, 28 Dec 2024 21:14:18 -0600 Subject: [PATCH 3/7] fix(job): remove old region create_job (#9914) --- jobs/v3/src/main/java/com/google/samples/BasicJobSample.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jobs/v3/src/main/java/com/google/samples/BasicJobSample.java b/jobs/v3/src/main/java/com/google/samples/BasicJobSample.java index 69c373ea3ca..e6f1275c933 100644 --- a/jobs/v3/src/main/java/com/google/samples/BasicJobSample.java +++ b/jobs/v3/src/main/java/com/google/samples/BasicJobSample.java @@ -73,7 +73,6 @@ public static Job generateJobWithRequiredFields(String companyName) { // [END job_basic_job] // [START job_create_job] - // [START create_job] /** Create a job. */ public static Job createJob(Job jobToBeCreated) throws IOException { @@ -93,7 +92,6 @@ public static Job createJob(Job jobToBeCreated) throws IOException { throw e; } } - // [END create_job] // [END job_create_job] // [START job_get_job] From db76fdc44b1f35bf3509257ddf2f679398e2300e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B5=D1=82=D1=8F=D0=BD=D0=B0=20=D0=AF=D0=B3=D0=BE?= =?UTF-8?q?=D0=B4=D1=81=D1=8C=D0=BA=D0=B0?= <49729677+TetyanaYahodska@users.noreply.github.com> Date: Mon, 30 Dec 2024 10:05:18 +0100 Subject: [PATCH 4/7] feat(compute): attach/ remove snapshot schedule to disk (#9791) * Implemented compute_snapshot_schedule_attach sample, created test * Implemented compute_snapshot_schedule_remove sample, created test * Fixed code * Fixed code as requested in the comments --- .../AttachSnapshotScheduleToDisk.java | 77 +++++++++++++++ .../RemoveSnapshotScheduleFromDisk.java | 81 ++++++++++++++++ .../snapshotschedule/SnapshotScheduleIT.java | 96 +++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 compute/cloud-client/src/main/java/compute/snapshotschedule/AttachSnapshotScheduleToDisk.java create mode 100644 compute/cloud-client/src/main/java/compute/snapshotschedule/RemoveSnapshotScheduleFromDisk.java create mode 100644 compute/cloud-client/src/test/java/compute/snapshotschedule/SnapshotScheduleIT.java diff --git a/compute/cloud-client/src/main/java/compute/snapshotschedule/AttachSnapshotScheduleToDisk.java b/compute/cloud-client/src/main/java/compute/snapshotschedule/AttachSnapshotScheduleToDisk.java new file mode 100644 index 00000000000..c68603f3ab6 --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/snapshotschedule/AttachSnapshotScheduleToDisk.java @@ -0,0 +1,77 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.snapshotschedule; + +// [START compute_snapshot_schedule_attach] +import com.google.cloud.compute.v1.AddResourcePoliciesDiskRequest; +import com.google.cloud.compute.v1.DisksAddResourcePoliciesRequest; +import com.google.cloud.compute.v1.DisksClient; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class AttachSnapshotScheduleToDisk { + public static void main(String[] args) throws Exception { + // TODO(developer): Replace these variables before running the sample. + // Project ID or project number of the Cloud project you want to use. + String projectId = "YOUR_PROJECT_ID"; + // Name of the zone where your disk is located. + String zone = "us-central1-a"; + // Name of the disk you want to attach the snapshot schedule to. + String diskName = "YOUR_DISK_NAME"; + // Name of the snapshot schedule you want to attach. + String snapshotScheduleName = "YOUR_SNAPSHOT_SCHEDULE_NAME"; + // Name of the region where your snapshot schedule is located. + String region = "us-central1"; + + attachSnapshotScheduleToDisk(projectId, zone, diskName, snapshotScheduleName, region); + } + + // Attaches a snapshot schedule to a disk. + public static Status attachSnapshotScheduleToDisk( + String projectId, String zone, String diskName, String snapshotScheduleName, String region) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + + String resourcePolicyLink = String.format( + "projects/%s/regions/%s/resourcePolicies/%s", projectId, region, snapshotScheduleName); + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (DisksClient disksClient = DisksClient.create()) { + + AddResourcePoliciesDiskRequest request = AddResourcePoliciesDiskRequest.newBuilder() + .setProject(projectId) + .setZone(zone) + .setDisk(diskName) + .setDisksAddResourcePoliciesRequestResource( + DisksAddResourcePoliciesRequest.newBuilder() + .addResourcePolicies(resourcePolicyLink) + .build()) + .build(); + + Operation response = disksClient.addResourcePoliciesAsync(request).get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error attaching snapshot schedule to disk: " + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_snapshot_schedule_attach] \ No newline at end of file diff --git a/compute/cloud-client/src/main/java/compute/snapshotschedule/RemoveSnapshotScheduleFromDisk.java b/compute/cloud-client/src/main/java/compute/snapshotschedule/RemoveSnapshotScheduleFromDisk.java new file mode 100644 index 00000000000..5fee20934b4 --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/snapshotschedule/RemoveSnapshotScheduleFromDisk.java @@ -0,0 +1,81 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.snapshotschedule; + +// [START compute_snapshot_schedule_remove] +import com.google.cloud.compute.v1.DisksClient; +import com.google.cloud.compute.v1.DisksRemoveResourcePoliciesRequest; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import com.google.cloud.compute.v1.RemoveResourcePoliciesDiskRequest; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class RemoveSnapshotScheduleFromDisk { + + public static void main(String[] args) throws Exception { + // TODO(developer): Replace these variables before running the sample. + // Project ID or project number of the Cloud project you want to use. + String projectId = "YOUR_PROJECT_ID"; + // Name of the zone where your disk is located. + String zone = "us-central1-a"; + // Name of the disk you want to remove the snapshot schedule from. + String diskName = "YOUR_DISK_NAME"; + // Name of the region where your snapshot schedule is located. + String region = "us-central1"; + // Name of the snapshot schedule you want to remove. + String snapshotScheduleName = "YOUR_SNAPSHOT_SCHEDULE_NAME"; + + removeSnapshotScheduleFromDisk(projectId, zone, diskName, region, snapshotScheduleName); + } + + // Removes snapshot schedule from a zonal disk. + public static Status removeSnapshotScheduleFromDisk( + String project, String zone, String diskName, String region, String snapshotScheduleName) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + String snapshotSchedulePath = String.format("projects/%s/regions/%s/resourcePolicies/%s", + project, region, snapshotScheduleName); + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (DisksClient disksClient = DisksClient.create()) { + DisksRemoveResourcePoliciesRequest disksRequest = + DisksRemoveResourcePoliciesRequest.newBuilder() + .addResourcePolicies(snapshotSchedulePath) + .build(); + + RemoveResourcePoliciesDiskRequest request = + RemoveResourcePoliciesDiskRequest.newBuilder() + .setProject(project) + .setZone(zone) + .setDisk(diskName) + .setDisksRemoveResourcePoliciesRequestResource(disksRequest) + .build(); + + Operation response = disksClient.removeResourcePoliciesAsync(request) + .get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Failed to remove resource policies from disk!" + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_snapshot_schedule_remove] \ No newline at end of file diff --git a/compute/cloud-client/src/test/java/compute/snapshotschedule/SnapshotScheduleIT.java b/compute/cloud-client/src/test/java/compute/snapshotschedule/SnapshotScheduleIT.java new file mode 100644 index 00000000000..82984538def --- /dev/null +++ b/compute/cloud-client/src/test/java/compute/snapshotschedule/SnapshotScheduleIT.java @@ -0,0 +1,96 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.snapshotschedule; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.compute.v1.AddResourcePoliciesDiskRequest; +import com.google.cloud.compute.v1.DisksClient; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import com.google.cloud.compute.v1.RemoveResourcePoliciesDiskRequest; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.MockedStatic; + +@RunWith(JUnit4.class) +@Timeout(value = 6, unit = TimeUnit.MINUTES) +public class SnapshotScheduleIT { + private static final String PROJECT_ID = "GOOGLE_CLOUD_PROJECT"; + private static final String ZONE = "asia-south1-a"; + private static final String REGION = ZONE.substring(0, ZONE.lastIndexOf('-')); + private static final String SCHEDULE_FOR_DISK = "test-schedule-for-disk"; + private static final String DISK_NAME = "gcloud-test-disk"; + + @Test + public void testAttachSnapshotScheduleToDisk() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + try (MockedStatic mockedDisksClient = mockStatic(DisksClient.class)) { + DisksClient mockClient = mock(DisksClient.class); + Operation operation = mock(Operation.class); + OperationFuture mockFuture = mock(OperationFuture.class); + + mockedDisksClient.when(DisksClient::create).thenReturn(mockClient); + when(mockClient.addResourcePoliciesAsync(any(AddResourcePoliciesDiskRequest.class))) + .thenReturn(mockFuture); + when(mockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(operation); + when(operation.getStatus()).thenReturn(Status.DONE); + + Status actualStatus = AttachSnapshotScheduleToDisk.attachSnapshotScheduleToDisk( + PROJECT_ID, ZONE, DISK_NAME, SCHEDULE_FOR_DISK, REGION); + + verify(mockClient, times(1)).addResourcePoliciesAsync(any()); + assertEquals(Status.DONE, actualStatus); + } + } + + @Test + public void testRemoveSnapshotScheduleFromDisk() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + try (MockedStatic mockedDisksClient = mockStatic(DisksClient.class)) { + DisksClient mockClient = mock(DisksClient.class); + Operation operation = mock(Operation.class); + OperationFuture mockFuture = mock(OperationFuture.class); + + mockedDisksClient.when(DisksClient::create).thenReturn(mockClient); + when(mockClient.removeResourcePoliciesAsync(any(RemoveResourcePoliciesDiskRequest.class))) + .thenReturn(mockFuture); + when(mockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(operation); + when(operation.getStatus()).thenReturn(Status.DONE); + + Status actualStatus = RemoveSnapshotScheduleFromDisk.removeSnapshotScheduleFromDisk( + PROJECT_ID, ZONE, DISK_NAME, REGION, SCHEDULE_FOR_DISK); + + verify(mockClient, times(1)).removeResourcePoliciesAsync(any()); + assertEquals(Status.DONE, actualStatus); + } + } +} From 1e9647e0b6d0e3e72f83b54eb3f583e35c5b5b02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B5=D1=82=D1=8F=D0=BD=D0=B0=20=D0=AF=D0=B3=D0=BE?= =?UTF-8?q?=D0=B4=D1=81=D1=8C=D0=BA=D0=B0?= <49729677+TetyanaYahodska@users.noreply.github.com> Date: Mon, 30 Dec 2024 11:10:40 +0100 Subject: [PATCH 5/7] feat(compute): add compute consistency group clone sample (#9885) * Implemented compute_consistency_group_clone and compute_consistency_group_clone_regional_disk samples, created tests * Fixed naming --- ...loneRegionalDisksFromConsistencyGroup.java | 73 +++++++++++++++++++ .../CloneZonalDisksFromConsistencyGroup.java | 73 +++++++++++++++++++ .../compute/disks/ConsistencyGroupIT.java | 53 ++++++++++++++ 3 files changed, 199 insertions(+) create mode 100644 compute/cloud-client/src/main/java/compute/disks/consistencygroup/CloneRegionalDisksFromConsistencyGroup.java create mode 100644 compute/cloud-client/src/main/java/compute/disks/consistencygroup/CloneZonalDisksFromConsistencyGroup.java diff --git a/compute/cloud-client/src/main/java/compute/disks/consistencygroup/CloneRegionalDisksFromConsistencyGroup.java b/compute/cloud-client/src/main/java/compute/disks/consistencygroup/CloneRegionalDisksFromConsistencyGroup.java new file mode 100644 index 00000000000..b7b0585902d --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/disks/consistencygroup/CloneRegionalDisksFromConsistencyGroup.java @@ -0,0 +1,73 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.disks.consistencygroup; + +// [START compute_consistency_group_clone_regional_disk] +import com.google.cloud.compute.v1.BulkInsertDiskResource; +import com.google.cloud.compute.v1.BulkInsertRegionDiskRequest; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import com.google.cloud.compute.v1.RegionDisksClient; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class CloneRegionalDisksFromConsistencyGroup { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // Project ID or project number of the Cloud project you want to use. + String project = "YOUR_PROJECT_ID"; + // Region in which your disks and consistency group are located. + String region = "us-central1"; + // Name of the consistency group you want to clone disks from. + String consistencyGroupName = "YOUR_CONSISTENCY_GROUP_NAME"; + + cloneRegionalDisksFromConsistencyGroup(project, region, consistencyGroupName); + } + + // Clones regional disks from a consistency group. + public static Status cloneRegionalDisksFromConsistencyGroup( + String project, String region, String consistencyGroupName) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + String sourceConsistencyGroupPolicy = String.format( + "projects/%s/regions/%s/resourcePolicies/%s", project, region, consistencyGroupName); + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (RegionDisksClient disksClient = RegionDisksClient.create()) { + BulkInsertRegionDiskRequest request = BulkInsertRegionDiskRequest.newBuilder() + .setProject(project) + .setRegion(region) + .setBulkInsertDiskResourceResource( + BulkInsertDiskResource.newBuilder() + .setSourceConsistencyGroupPolicy(sourceConsistencyGroupPolicy) + .build()) + .build(); + + Operation response = disksClient.bulkInsertAsync(request).get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error cloning regional disks! " + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_consistency_group_clone_regional_disk] diff --git a/compute/cloud-client/src/main/java/compute/disks/consistencygroup/CloneZonalDisksFromConsistencyGroup.java b/compute/cloud-client/src/main/java/compute/disks/consistencygroup/CloneZonalDisksFromConsistencyGroup.java new file mode 100644 index 00000000000..b819829a100 --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/disks/consistencygroup/CloneZonalDisksFromConsistencyGroup.java @@ -0,0 +1,73 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.disks.consistencygroup; + +// [START compute_consistency_group_clone] +import com.google.cloud.compute.v1.BulkInsertDiskRequest; +import com.google.cloud.compute.v1.BulkInsertDiskResource; +import com.google.cloud.compute.v1.DisksClient; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class CloneZonalDisksFromConsistencyGroup { + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // Project ID or project number of the Cloud project you want to use. + String project = "YOUR_PROJECT_ID"; + // Zone in which your disks are located. + String zone = "us-central1-a"; + // Name of the consistency group you want to clone disks from. + String consistencyGroupName = "YOUR_CONSISTENCY_GROUP_NAME"; + + cloneZonalDisksFromConsistencyGroup(project, zone, consistencyGroupName); + } + + // Clones zonal disks from a consistency group. + public static Status cloneZonalDisksFromConsistencyGroup( + String project, String zone, String consistencyGroupName) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + String region = zone.substring(0, zone.lastIndexOf('-')); + String sourceConsistencyGroupPolicy = String.format( + "projects/%s/regions/%s/resourcePolicies/%s", project, region, consistencyGroupName); + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (DisksClient disksClient = DisksClient.create()) { + BulkInsertDiskRequest request = BulkInsertDiskRequest.newBuilder() + .setProject(project) + .setZone(zone) + .setBulkInsertDiskResourceResource( + BulkInsertDiskResource.newBuilder() + .setSourceConsistencyGroupPolicy(sourceConsistencyGroupPolicy) + .build()) + .build(); + + Operation response = disksClient.bulkInsertAsync(request).get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error cloning zonal disks! " + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_consistency_group_clone] diff --git a/compute/cloud-client/src/test/java/compute/disks/ConsistencyGroupIT.java b/compute/cloud-client/src/test/java/compute/disks/ConsistencyGroupIT.java index e7038724d45..7f96e34dfd8 100644 --- a/compute/cloud-client/src/test/java/compute/disks/ConsistencyGroupIT.java +++ b/compute/cloud-client/src/test/java/compute/disks/ConsistencyGroupIT.java @@ -27,6 +27,8 @@ import com.google.api.gax.longrunning.OperationFuture; import com.google.cloud.compute.v1.AddResourcePoliciesRegionDiskRequest; +import com.google.cloud.compute.v1.BulkInsertDiskRequest; +import com.google.cloud.compute.v1.BulkInsertRegionDiskRequest; import com.google.cloud.compute.v1.DisksClient; import com.google.cloud.compute.v1.InsertResourcePolicyRequest; import com.google.cloud.compute.v1.ListDisksRequest; @@ -39,6 +41,8 @@ import com.google.cloud.compute.v1.StopGroupAsyncReplicationDiskRequest; import com.google.cloud.compute.v1.StopGroupAsyncReplicationRegionDiskRequest; import compute.disks.consistencygroup.AddDiskToConsistencyGroup; +import compute.disks.consistencygroup.CloneRegionalDisksFromConsistencyGroup; +import compute.disks.consistencygroup.CloneZonalDisksFromConsistencyGroup; import compute.disks.consistencygroup.CreateConsistencyGroup; import compute.disks.consistencygroup.DeleteConsistencyGroup; import compute.disks.consistencygroup.ListRegionalDisksInConsistencyGroup; @@ -248,4 +252,53 @@ public void testStopZonalDiskReplicationConsistencyGroup() throws Exception { assertEquals(Status.DONE, status); } } + + @Test + public void testCloneRegionalDisksFromConsistencyGroup() throws Exception { + try (MockedStatic mockedRegionDisksClient = + mockStatic(RegionDisksClient.class)) { + Operation operation = mock(Operation.class); + RegionDisksClient mockClient = mock(RegionDisksClient.class); + OperationFuture mockFuture = mock(OperationFuture.class); + + mockedRegionDisksClient.when(RegionDisksClient::create).thenReturn(mockClient); + when(mockClient.bulkInsertAsync(any(BulkInsertRegionDiskRequest.class))) + .thenReturn(mockFuture); + when(mockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(operation); + when(operation.getStatus()).thenReturn(Status.DONE); + + Status status = CloneRegionalDisksFromConsistencyGroup + .cloneRegionalDisksFromConsistencyGroup( + PROJECT_ID, REGION, CONSISTENCY_GROUP_NAME); + + verify(mockClient, times(1)) + .bulkInsertAsync(any(BulkInsertRegionDiskRequest.class)); + verify(mockFuture, times(1)).get(anyLong(), any(TimeUnit.class)); + assertEquals(Status.DONE, status); + } + } + + @Test + public void testCloneZonalDisksFromConsistencyGroup() throws Exception { + try (MockedStatic mockedRegionDisksClient = + mockStatic(DisksClient.class)) { + Operation operation = mock(Operation.class); + DisksClient mockClient = mock(DisksClient.class); + OperationFuture mockFuture = mock(OperationFuture.class); + + mockedRegionDisksClient.when(DisksClient::create).thenReturn(mockClient); + when(mockClient.bulkInsertAsync(any(BulkInsertDiskRequest.class))) + .thenReturn(mockFuture); + when(mockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(operation); + when(operation.getStatus()).thenReturn(Status.DONE); + + Status status = CloneZonalDisksFromConsistencyGroup + .cloneZonalDisksFromConsistencyGroup(PROJECT_ID, REGION, CONSISTENCY_GROUP_NAME); + + verify(mockClient, times(1)) + .bulkInsertAsync(any(BulkInsertDiskRequest.class)); + verify(mockFuture, times(1)).get(anyLong(), any(TimeUnit.class)); + assertEquals(Status.DONE, status); + } + } } \ No newline at end of file From 206512e346d3e952537e7e2561e8c5cd6cd833c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B5=D1=82=D1=8F=D0=BD=D0=B0=20=D0=AF=D0=B3=D0=BE?= =?UTF-8?q?=D0=B4=D1=81=D1=8C=D0=BA=D0=B0?= <49729677+TetyanaYahodska@users.noreply.github.com> Date: Mon, 30 Dec 2024 11:58:17 +0100 Subject: [PATCH 6/7] feat(compute): add compute instance attach regional disk force sample (#9730) * Implemented compute_instance_attach_regional_disk_force sample, created test * Added clean up method * Fixed comments and parameters * Test order deleted * Fixed code * Fixed code * Fixed code * Increased timeout * Increased timeout * Increased timeout * Fixed code * Fixed code * Fixed code * Fixed naming --- .../disks/AttachRegionalDiskForce.java | 81 +++++++++++++++++++ .../compute/disks/InstanceAttachDiskIT.java | 75 +++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 compute/cloud-client/src/main/java/compute/disks/AttachRegionalDiskForce.java create mode 100644 compute/cloud-client/src/test/java/compute/disks/InstanceAttachDiskIT.java diff --git a/compute/cloud-client/src/main/java/compute/disks/AttachRegionalDiskForce.java b/compute/cloud-client/src/main/java/compute/disks/AttachRegionalDiskForce.java new file mode 100644 index 00000000000..20e13376e5e --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/disks/AttachRegionalDiskForce.java @@ -0,0 +1,81 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.disks; + +// [START compute_instance_attach_regional_disk_force] +import com.google.cloud.compute.v1.AttachDiskInstanceRequest; +import com.google.cloud.compute.v1.AttachedDisk; +import com.google.cloud.compute.v1.InstancesClient; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class AttachRegionalDiskForce { + public static void main(String[] args) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // Project ID or project number of the Cloud project you want to use. + String projectId = "YOUR_PROJECT_ID"; + // Name of the zone of your compute instance. + String zone = "us-central1-a"; + // The name of the compute instance where you are adding the replicated disk. + String instanceName = "YOUR_INSTANCE_NAME"; + // The region where your replicated disk is located. + String region = "us-central1"; + // The name of the replicated disk. + String diskName = "YOUR_DISK_NAME"; + + attachRegionalDiskForce(projectId, zone, instanceName, region, diskName); + } + + // Attaches a regional disk to the instance, + // forcing the attachment even if other VMs are using the disk. + public static Status attachRegionalDiskForce(String projectId, + String zone, String instanceName, String region, String diskName) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + String diskLink = String.format("projects/%s/regions/%s/disks/%s", + projectId, region, diskName); + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (InstancesClient instancesClient = InstancesClient.create()) { + AttachedDisk attachedDisk = AttachedDisk.newBuilder() + .setSource(diskLink) + .setMode(AttachedDisk.Mode.READ_WRITE.toString()) + .build(); + + AttachDiskInstanceRequest attachDiskRequest = AttachDiskInstanceRequest.newBuilder() + .setProject(projectId) + .setZone(zone) + .setInstance(instanceName) + .setAttachedDiskResource(attachedDisk) + .setForceAttach(true) // Force the attachment + .build(); + + Operation response = instancesClient.attachDiskAsync(attachDiskRequest) + .get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error attaching regional disk! " + response); + } + return response.getStatus(); + } + } +} +// [END compute_instance_attach_regional_disk_force] diff --git a/compute/cloud-client/src/test/java/compute/disks/InstanceAttachDiskIT.java b/compute/cloud-client/src/test/java/compute/disks/InstanceAttachDiskIT.java new file mode 100644 index 00000000000..47ba47b66df --- /dev/null +++ b/compute/cloud-client/src/test/java/compute/disks/InstanceAttachDiskIT.java @@ -0,0 +1,75 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.disks; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.api.gax.longrunning.OperationFuture; +import com.google.cloud.compute.v1.AttachDiskInstanceRequest; +import com.google.cloud.compute.v1.InstancesClient; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.MockedStatic; + +@RunWith(JUnit4.class) +@Timeout(value = 4, unit = TimeUnit.MINUTES) +public class InstanceAttachDiskIT { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String ZONE = "us-west1-a"; + private static final String REGION = "us-west1"; + private static final String ATTACHED_DISK = "disk-regional"; + private static final String INSTANCE_NAME = "instance"; + + @Test + public void testAttachRegionalDiskForceAttach() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + try (MockedStatic mockedResourcePoliciesClient = + mockStatic(InstancesClient.class)) { + Operation operation = mock(Operation.class); + InstancesClient mockClient = mock(InstancesClient.class); + OperationFuture mockFuture = mock(OperationFuture.class); + + mockedResourcePoliciesClient.when(InstancesClient::create).thenReturn(mockClient); + when(mockClient.attachDiskAsync(any(AttachDiskInstanceRequest.class))) + .thenReturn(mockFuture); + when(mockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(operation); + when(operation.getStatus()).thenReturn(Status.DONE); + + Status status = AttachRegionalDiskForce + .attachRegionalDiskForce(PROJECT_ID, ZONE, INSTANCE_NAME, REGION, ATTACHED_DISK); + + verify(mockClient, times(1)).attachDiskAsync(any(AttachDiskInstanceRequest.class)); + verify(mockFuture, times(1)).get(anyLong(), any(TimeUnit.class)); + assertEquals(Status.DONE, status); + } + } +} From 673b387a82e05ed7e25f2ce8ea671db833a2bb02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A2=D0=B5=D1=82=D1=8F=D0=BD=D0=B0=20=D0=AF=D0=B3=D0=BE?= =?UTF-8?q?=D0=B4=D1=81=D1=8C=D0=BA=D0=B0?= <49729677+TetyanaYahodska@users.noreply.github.com> Date: Mon, 30 Dec 2024 12:38:24 +0100 Subject: [PATCH 7/7] feat(compute): add compute disk create secondary custom sample (#9644) * Implemented compute_disk_create_secondary_custom sample, created test * Fixed code * Fixed variable * Fixed code * Fixed whitespace * Fixed whitespace --- .../disks/CreateSecondaryCustomDisk.java | 111 ++++++++++++++++++ .../src/test/java/compute/disks/DisksIT.java | 23 +++- 2 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 compute/cloud-client/src/main/java/compute/disks/CreateSecondaryCustomDisk.java diff --git a/compute/cloud-client/src/main/java/compute/disks/CreateSecondaryCustomDisk.java b/compute/cloud-client/src/main/java/compute/disks/CreateSecondaryCustomDisk.java new file mode 100644 index 00000000000..cf952c3e522 --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/disks/CreateSecondaryCustomDisk.java @@ -0,0 +1,111 @@ +/* + * Copyright 2024 Google LLC + * + * 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 compute.disks; + +//[START compute_disk_create_secondary_custom] +import com.google.cloud.compute.v1.Disk; +import com.google.cloud.compute.v1.DiskAsyncReplication; +import com.google.cloud.compute.v1.DisksClient; +import com.google.cloud.compute.v1.GuestOsFeature; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class CreateSecondaryCustomDisk { + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // The project that contains the primary disk. + String primaryProjectId = "PRIMARY_PROJECT_ID"; + // The project that contains the secondary disk. + String secondaryProjectId = "SECONDARY_PROJECT_ID"; + // Name of the primary disk you want to use. + String primaryDiskName = "PRIMARY_DISK_NAME"; + // Name of the zone in which your primary disk is located. + // Learn more about zones and regions: + // https://cloud.google.com/compute/docs/disks/async-pd/about#supported_region_pairs + String primaryDiskZone = "us-central1-a"; + // Name of the disk you want to create. + String secondaryDiskName = "SECONDARY_DISK_NAME"; + // Name of the zone in which you want to create the secondary disk. + String secondaryDiskZone = "us-east1-c"; + // Size of the new disk in gigabytes. + long diskSizeGb = 30L; + // The type of the disk you want to create. This value uses the following format: + // "projects/{projectId}/zones/{zone}/diskTypes/ + // (pd-standard|pd-ssd|pd-balanced|pd-extreme)". + String diskType = String.format( + "projects/%s/zones/%s/diskTypes/pd-balanced", secondaryProjectId, secondaryDiskZone); + + createSecondaryCustomDisk(primaryProjectId, secondaryProjectId, primaryDiskName, + secondaryDiskName, primaryDiskZone, secondaryDiskZone, diskSizeGb, diskType); + } + + // Creates a secondary disk with specified custom parameters. + public static Status createSecondaryCustomDisk(String primaryProjectId, String secondaryProjectId, + String primaryDiskName, String secondaryDiskName, String primaryDiskZone, + String secondaryDiskZone, long diskSizeGb, String diskType) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (DisksClient disksClient = DisksClient.create()) { + String primaryDiskSource = String.format("projects/%s/zones/%s/disks/%s", + primaryProjectId, primaryDiskZone, primaryDiskName); + + DiskAsyncReplication asyncReplication = DiskAsyncReplication.newBuilder() + .setDisk(primaryDiskSource) + .build(); + + // Define the guest OS features. + List guestOsFeatures = Arrays.asList( + GuestOsFeature.newBuilder().setType("UEFI_COMPATIBLE").build(), + GuestOsFeature.newBuilder().setType("GVNIC").build(), + GuestOsFeature.newBuilder().setType("MULTI_IP_SUBNET").build()); + + // Define the labels. + Map labels = new HashMap<>(); + labels.put("secondary-disk-for-replication", "yes"); + + Disk disk = Disk.newBuilder() + .setName(secondaryDiskName) + .setSizeGb(diskSizeGb) + .setType(diskType) + .setZone(secondaryDiskZone) + .addAllGuestOsFeatures(guestOsFeatures) + .putAllLabels(labels) + .setAsyncPrimaryDisk(asyncReplication) + .build(); + + // Wait for the create disk operation to complete. + Operation response = disksClient.insertAsync(secondaryProjectId, secondaryDiskZone, disk) + .get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error creating secondary custom disks! " + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_disk_create_secondary_custom] diff --git a/compute/cloud-client/src/test/java/compute/disks/DisksIT.java b/compute/cloud-client/src/test/java/compute/disks/DisksIT.java index 2e075d663e5..be41028588d 100644 --- a/compute/cloud-client/src/test/java/compute/disks/DisksIT.java +++ b/compute/cloud-client/src/test/java/compute/disks/DisksIT.java @@ -40,6 +40,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.lang.Error; import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -79,6 +80,8 @@ public class DisksIT { private static String SECONDARY_REGIONAL_DISK; private static String SECONDARY_DISK; private static final long DISK_SIZE = 10L; + private static String SECONDARY_CUSTOM_DISK; + private ByteArrayOutputStream stdOut; // Check if the required environment variables are set. @@ -109,6 +112,7 @@ public static void setup() REGIONAL_REPLICATED_DISK = "gcloud-test-disk-replicated-" + uuid; SECONDARY_REGIONAL_DISK = "gcloud-test-disk-secondary-regional-" + uuid; SECONDARY_DISK = "gcloud-test-disk-secondary-" + uuid; + SECONDARY_CUSTOM_DISK = "gcloud-test-disk-custom-" + uuid; // Cleanup existing stale resources. Util.cleanUpExistingInstances("test-disks", PROJECT_ID, ZONE); @@ -186,6 +190,7 @@ public static void cleanUp() RegionalDelete.deleteRegionalDisk(PROJECT_ID, REGION, REGIONAL_REPLICATED_DISK); RegionalDelete.deleteRegionalDisk(PROJECT_ID, "us-central1", SECONDARY_REGIONAL_DISK); DeleteDisk.deleteDisk(PROJECT_ID, "us-central1-c", SECONDARY_DISK); + DeleteDisk.deleteDisk(PROJECT_ID, "us-central1-c", SECONDARY_CUSTOM_DISK); stdOut.close(); System.setOut(out); @@ -343,14 +348,28 @@ public void testCreateDiskSecondaryRegional() @Test public void testCreateDiskSecondaryZonal() throws IOException, ExecutionException, InterruptedException, TimeoutException { - String diskType = String.format( + String diskType = String.format( "projects/%s/zones/%s/diskTypes/pd-ssd", PROJECT_ID, ZONE); Status status = CreateDiskSecondaryZonal.createDiskSecondaryZonal( PROJECT_ID, PROJECT_ID, EMPTY_DISK_NAME, SECONDARY_DISK, ZONE, - "us-central1-c", DISK_SIZE, diskType); + "us-central1-c", DISK_SIZE, diskType); Disk disk = Util.getDisk(PROJECT_ID, "us-central1-c", SECONDARY_DISK); assertThat(status).isEqualTo(Status.DONE); assertEquals(SECONDARY_DISK, disk.getName()); } + + @Test + public void testCreateSecondaryCustomDisk() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + String diskType = String.format( + "projects/%s/zones/%s/diskTypes/pd-ssd", PROJECT_ID, ZONE); + Status status = CreateSecondaryCustomDisk.createSecondaryCustomDisk( + PROJECT_ID, PROJECT_ID, EMPTY_DISK_NAME, SECONDARY_CUSTOM_DISK, ZONE, + "us-central1-c", DISK_SIZE, diskType); + Disk disk = Util.getDisk(PROJECT_ID, "us-central1-c", SECONDARY_CUSTOM_DISK); + + assertThat(status).isEqualTo(Status.DONE); + assertEquals(SECONDARY_CUSTOM_DISK, disk.getName()); + } }