From b9ab725a6b219a439f1c32e97af792ccbf4d4c80 Mon Sep 17 00:00:00 2001 From: SitaLakshmi Date: Mon, 4 Apr 2022 16:36:57 +0530 Subject: [PATCH 1/3] docs(compute-samples): added samples and test for windows os image creation --- .../windowsosimage/CreateWindowsOSImage.java | 132 ++++++++++++++ .../windowsosimage/WindowsOSImageIT.java | 170 ++++++++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOSImage.java create mode 100644 compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOSImageIT.java diff --git a/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOSImage.java b/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOSImage.java new file mode 100644 index 00000000000..f508a75d9cb --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOSImage.java @@ -0,0 +1,132 @@ +// Copyright 2022 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.windowsosimage; + +// [START compute_windows_image_create] + +import com.google.cloud.compute.v1.Disk; +import com.google.cloud.compute.v1.DisksClient; +import com.google.cloud.compute.v1.Image; +import com.google.cloud.compute.v1.ImagesClient; +import com.google.cloud.compute.v1.InsertImageRequest; +import com.google.cloud.compute.v1.Instance; +import com.google.cloud.compute.v1.InstancesClient; +import com.google.cloud.compute.v1.Operation; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +public class CreateWindowsOSImage { + + public static void main(String[] args) + throws IOException, ExecutionException, InterruptedException { + // TODO(developer): Replace these variables before running the sample. + + // Project ID or project number of the Cloud project you use. + String project = "your-project-id"; + // Zone of the disk you copy from. + String zone = "europe-central2-b"; + // Name of the source disk you copy from. + String sourceDiskName = "source-disk-name"; + // Name of the image you want to create. + String imageName = "your-image-name"; + // Storage location for the image. If the value is undefined, + // function will store the image in the multi-region closest to your image's source location. + String storageLocation = "eu"; + // Create the image even if the source disk is attached to a running instance. + boolean forceCreate = false; + + createWindowsOSImage(project, zone, sourceDiskName, imageName, storageLocation, forceCreate); + } + + // Creates a new Windows image from the specified source disk. + public static void createWindowsOSImage(String project, String zone, String sourceDiskName, + String imageName, String storageLocation, boolean forceCreate) + throws IOException, ExecutionException, InterruptedException { + + try (ImagesClient imagesClient = ImagesClient.create(); + InstancesClient instancesClient = InstancesClient.create(); + DisksClient disksClient = DisksClient.create()) { + + Disk disk = disksClient.get(project, zone, sourceDiskName); + + // Getting instances where source disk is attached. + for (String fullInstanceName : disk.getUsersList()) { + Map instanceInfo = parseInstanceName(fullInstanceName); + Instance instance = instancesClient.get(instanceInfo.get("instanceProjectId"), + instanceInfo.get("instanceZone"), instanceInfo.get("instanceName")); + + // Сhecking whether the instances is stopped. + if (!Arrays.asList("TERMINATED", "STOPPED").contains(instance.getStatus()) + && !forceCreate) { + throw new IllegalStateException( + String.format( + "Instance %s should be stopped. Please stop the instance using GCESysprep command or set forceCreate parameter to true (not recommended). More information here: https://cloud.google.com/compute/docs/instances/windows/creating-windows-os-image#api.", + instanceInfo.get("instanceName"))); + } + } + + if (forceCreate) { + System.out.println( + "Warning: forceCreate option compromise the integrity of your image. " + + "Stop the instance before you create the image if possible."); + } + + // Create Image. + Image image = Image.newBuilder() + .setName(imageName) + .setSourceDisk(String.format("/zones/%s/disks/%s", zone, sourceDiskName)) + .addStorageLocations(storageLocation.isEmpty() ? "" : storageLocation) + .build(); + + InsertImageRequest insertImageRequest = InsertImageRequest.newBuilder() + .setProject(project) + .setForceCreate(forceCreate) + .setImageResource(image) + .build(); + + Operation response = imagesClient.insertAsync(insertImageRequest).get(); + + if (response.hasError()) { + System.out.println("Windows OS Image creation failed ! ! " + response); + return; + } + + System.out.println("Image created."); + } + } + + + public static Map parseInstanceName(String name) { + String[] parsedName = name.split("/"); + int splitLength = parsedName.length; + + if (splitLength < 5) { + throw new IllegalArgumentException( + "Provide correct instance name in the following format: " + + "https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME"); + } + + return new HashMap<>() {{ + put("instanceName", parsedName[splitLength - 1]); + put("instanceZone", parsedName[splitLength - 3]); + put("instanceProjectId", parsedName[splitLength - 5]); + }}; + } + +} +// [END compute_windows_image_create] \ No newline at end of file diff --git a/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOSImageIT.java b/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOSImageIT.java new file mode 100644 index 00000000000..8082d84903a --- /dev/null +++ b/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOSImageIT.java @@ -0,0 +1,170 @@ +// Copyright 2022 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.windowsosimage; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import com.google.cloud.compute.v1.AttachedDisk; +import com.google.cloud.compute.v1.AttachedDiskInitializeParams; +import com.google.cloud.compute.v1.ImagesClient; +import com.google.cloud.compute.v1.InsertInstanceRequest; +import com.google.cloud.compute.v1.Instance; +import com.google.cloud.compute.v1.InstancesClient; +import com.google.cloud.compute.v1.NetworkInterface; +import com.google.cloud.compute.v1.Operation; +import compute.DeleteInstance; +import compute.Util; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class WindowsOSImageIT { + + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String ZONE = "us-central1-a"; + private static String INSTANCE_NAME; + private static String DISK_NAME; + private static String IMAGE_NAME; + @Rule + public ExpectedException expectedException = ExpectedException.none(); + private ByteArrayOutputStream stdOut; + + // Check if the required environment variables are set. + public static void requireEnvVar(String envVarName) { + assertWithMessage(String.format("Missing environment variable '%s' ", envVarName)) + .that(System.getenv(envVarName)).isNotEmpty(); + } + + @BeforeClass + public static void setup() throws IOException, ExecutionException, InterruptedException { + final PrintStream out = System.out; + ByteArrayOutputStream stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + + // Cleanup existing test instances. + Util.cleanUpExistingInstances("windowsimage-test-instance-", PROJECT_ID, ZONE); + + String randomUUID = UUID.randomUUID().toString().split("-")[0]; + INSTANCE_NAME = "windowsimage-test-instance-" + randomUUID; + DISK_NAME = "windowsimage-test-disk-" + randomUUID; + IMAGE_NAME = "windowsimage-test-image-" + randomUUID; + + // Create Instance with Windows source image. + try (InstancesClient instancesClient = InstancesClient.create()) { + AttachedDisk attachedDisk = AttachedDisk.newBuilder() + .setDeviceName(DISK_NAME) + .setAutoDelete(true) + .setBoot(true) + .setType(AttachedDisk.Type.PERSISTENT.name()) + .setInitializeParams(AttachedDiskInitializeParams.newBuilder() + .setDiskName(DISK_NAME) + .setDiskSizeGb(64) + .setSourceImage( + "projects/windows-cloud/global/images/windows-server-2012-r2-dc-core-v20220314") + .build()) + .build(); + + Instance instance = Instance.newBuilder() + .setName(INSTANCE_NAME) + .setMachineType(String.format("zones/%s/machineTypes/n1-standard-1", ZONE)) + .addNetworkInterfaces(NetworkInterface.newBuilder() + .setName("global/networks/default") + .build()) + .addDisks(attachedDisk) + .build(); + + InsertInstanceRequest request = InsertInstanceRequest.newBuilder() + .setProject(PROJECT_ID) + .setZone(ZONE) + .setInstanceResource(instance) + .build(); + + Operation response = instancesClient.insertAsync(request).get(); + Assert.assertFalse(response.hasError()); + } + + stdOut.close(); + System.setOut(out); + } + + @AfterClass + public static void cleanUp() throws IOException, ExecutionException, InterruptedException { + final PrintStream out = System.out; + ByteArrayOutputStream stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + + // Delete image. + ImagesClient imagesClient = ImagesClient.create(); + Operation operation = imagesClient.deleteAsync(PROJECT_ID, IMAGE_NAME).get(); + if (operation.hasError()) { + System.out.println("Image not deleted."); + } + + // Delete instance. + DeleteInstance.deleteInstance(PROJECT_ID, ZONE, INSTANCE_NAME); + + stdOut.close(); + System.setOut(out); + } + + @Before + public void beforeEach() { + stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + } + + @After + public void afterEach() { + stdOut = null; + System.setOut(null); + } + + + @Test + public void testCreateWindowsImage_failDueToRunningInstance() + throws IOException, ExecutionException, InterruptedException { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage(String.format("Instance %s should be stopped.", INSTANCE_NAME)); + CreateWindowsOSImage.createWindowsOSImage( + PROJECT_ID, ZONE, DISK_NAME, IMAGE_NAME, "eu", false); + } + + + @Test + public void testCreateWindowsImage_pass() + throws IOException, ExecutionException, InterruptedException { + CreateWindowsOSImage.createWindowsOSImage( + PROJECT_ID, ZONE, DISK_NAME, IMAGE_NAME, "eu", true); + assertThat(stdOut.toString()).contains("Image created."); + } + +} From d012b83aaa823bd8e2551ac9bc348b78e4b81c7e Mon Sep 17 00:00:00 2001 From: SitaLakshmi Date: Mon, 4 Apr 2022 16:49:15 +0530 Subject: [PATCH 2/3] docs(compute-samples): lint fix --- ...sOSImage.java => CreateWindowsOsImage.java} | 18 ++++++++++-------- ...owsOSImageIT.java => WindowsOsImageIT.java} | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) rename compute/cloud-client/src/main/java/compute/windowsosimage/{CreateWindowsOSImage.java => CreateWindowsOsImage.java} (92%) rename compute/cloud-client/src/test/java/compute/windowsosimage/{WindowsOSImageIT.java => WindowsOsImageIT.java} (97%) diff --git a/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOSImage.java b/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOsImage.java similarity index 92% rename from compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOSImage.java rename to compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOsImage.java index f508a75d9cb..8e2ea757002 100644 --- a/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOSImage.java +++ b/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOsImage.java @@ -30,7 +30,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; -public class CreateWindowsOSImage { +public class CreateWindowsOsImage { public static void main(String[] args) throws IOException, ExecutionException, InterruptedException { @@ -50,11 +50,11 @@ public static void main(String[] args) // Create the image even if the source disk is attached to a running instance. boolean forceCreate = false; - createWindowsOSImage(project, zone, sourceDiskName, imageName, storageLocation, forceCreate); + createWindowsOsImage(project, zone, sourceDiskName, imageName, storageLocation, forceCreate); } // Creates a new Windows image from the specified source disk. - public static void createWindowsOSImage(String project, String zone, String sourceDiskName, + public static void createWindowsOsImage(String project, String zone, String sourceDiskName, String imageName, String storageLocation, boolean forceCreate) throws IOException, ExecutionException, InterruptedException { @@ -121,11 +121,13 @@ public static Map parseInstanceName(String name) { + "https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME"); } - return new HashMap<>() {{ - put("instanceName", parsedName[splitLength - 1]); - put("instanceZone", parsedName[splitLength - 3]); - put("instanceProjectId", parsedName[splitLength - 5]); - }}; + return new HashMap<>() { + { + put("instanceName", parsedName[splitLength - 1]); + put("instanceZone", parsedName[splitLength - 3]); + put("instanceProjectId", parsedName[splitLength - 5]); + } + }; } } diff --git a/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOSImageIT.java b/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOsImageIT.java similarity index 97% rename from compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOSImageIT.java rename to compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOsImageIT.java index 8082d84903a..ce04012cf1b 100644 --- a/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOSImageIT.java +++ b/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOsImageIT.java @@ -44,7 +44,7 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) -public class WindowsOSImageIT { +public class WindowsOsImageIT { private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); private static final String ZONE = "us-central1-a"; @@ -154,7 +154,7 @@ public void testCreateWindowsImage_failDueToRunningInstance() throws IOException, ExecutionException, InterruptedException { expectedException.expect(IllegalStateException.class); expectedException.expectMessage(String.format("Instance %s should be stopped.", INSTANCE_NAME)); - CreateWindowsOSImage.createWindowsOSImage( + CreateWindowsOsImage.createWindowsOsImage( PROJECT_ID, ZONE, DISK_NAME, IMAGE_NAME, "eu", false); } @@ -162,7 +162,7 @@ public void testCreateWindowsImage_failDueToRunningInstance() @Test public void testCreateWindowsImage_pass() throws IOException, ExecutionException, InterruptedException { - CreateWindowsOSImage.createWindowsOSImage( + CreateWindowsOsImage.createWindowsOsImage( PROJECT_ID, ZONE, DISK_NAME, IMAGE_NAME, "eu", true); assertThat(stdOut.toString()).contains("Image created."); } From 6621aa0df97dee9bc61aee1671341f0fc8b84b6c Mon Sep 17 00:00:00 2001 From: SitaLakshmi Date: Mon, 11 Apr 2022 12:09:56 +0530 Subject: [PATCH 3/3] refactored snippet location --- .../osimage}/CreateWindowsOsImage.java | 2 +- .../{windowsosimage => windows/osimage}/WindowsOsImageIT.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename compute/cloud-client/src/main/java/compute/{windowsosimage => windows/osimage}/CreateWindowsOsImage.java (99%) rename compute/cloud-client/src/test/java/compute/{windowsosimage => windows/osimage}/WindowsOsImageIT.java (99%) diff --git a/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOsImage.java b/compute/cloud-client/src/main/java/compute/windows/osimage/CreateWindowsOsImage.java similarity index 99% rename from compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOsImage.java rename to compute/cloud-client/src/main/java/compute/windows/osimage/CreateWindowsOsImage.java index 8e2ea757002..a73d56142ad 100644 --- a/compute/cloud-client/src/main/java/compute/windowsosimage/CreateWindowsOsImage.java +++ b/compute/cloud-client/src/main/java/compute/windows/osimage/CreateWindowsOsImage.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package compute.windowsosimage; +package compute.windows.osimage; // [START compute_windows_image_create] diff --git a/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOsImageIT.java b/compute/cloud-client/src/test/java/compute/windows/osimage/WindowsOsImageIT.java similarity index 99% rename from compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOsImageIT.java rename to compute/cloud-client/src/test/java/compute/windows/osimage/WindowsOsImageIT.java index ce04012cf1b..82fb84ceab5 100644 --- a/compute/cloud-client/src/test/java/compute/windowsosimage/WindowsOsImageIT.java +++ b/compute/cloud-client/src/test/java/compute/windows/osimage/WindowsOsImageIT.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package compute.windowsosimage; +package compute.windows.osimage; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage;