Skip to content

Commit 69cad8c

Browse files
authored
mgmt samples, create trustedlaunch vm from galleryimage (#32264)
* add gen2 to KnownWindowsVirtualMachineImage * samples for creating trusted vm from azure image
1 parent d7b3b52 commit 69cad8c

File tree

9 files changed

+2144
-6
lines changed

9 files changed

+2144
-6
lines changed

sdk/resourcemanager/azure-resourcemanager-compute/CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
- Supported `copyCompletionPercent` and `copyCompletionError` method in `Snapshot` for retrieving `CopyStart` progress.
1010
- Supported `withTrustedLaunch`, `withSecureBoot` and `withVTpm` methods in `VirtualMachine`.
1111
- Supported `UBUNTU_SERVER_18_04_LTS_GEN2`, `UBUNTU_SERVER_20_04_LTS` and `UBUNTU_SERVER_20_04_LTS_GEN2` in `KnownLinuxVirtualMachineImage`.
12+
- Supported `WINDOWS_SERVER_2019_DATACENTER_GEN2`, `WINDOWS_SERVER_2019_DATACENTER_WITH_CONTAINERS_GEN2`,
13+
`WINDOWS_SERVER_2016_DATACENTER_GEN2` and `WINDOWS_DESKTOP_10_21H2_PRO_GEN2` in `KnownWindowsVirtualMachineImage`.
1214
- Supported `withTrustedLaunch` and `withHyperVGeneration` methods in `GalleryImage`.
1315

1416
### Breaking Changes

sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/implementation/GalleryImageImpl.java

+12-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import java.util.Iterator;
3636
import java.util.List;
3737
import java.util.Map;
38+
import java.util.stream.Collectors;
39+
import java.util.stream.Stream;
3840

3941
/** The implementation for GalleryImage and its create and update interfaces. */
4042
class GalleryImageImpl extends CreatableUpdatableImpl<GalleryImage, GalleryImageInner, GalleryImageImpl>
@@ -575,10 +577,16 @@ public GalleryImageImpl withHyperVGeneration(HyperVGeneration hyperVGeneration)
575577

576578
@Override
577579
public GalleryImageImpl withTrustedLaunch() {
578-
ensureFeatures().add(
579-
new GalleryImageFeature()
580-
.withName(FEATURE_SECURITY_TYPE)
581-
.withValue(SecurityTypes.TRUSTED_LAUNCH.toString()));
580+
this.innerModel().withFeatures(
581+
Stream.concat(
582+
ensureFeatures()
583+
.stream()
584+
.filter(feature -> !FEATURE_SECURITY_TYPE.equals(feature.name())),
585+
Stream.of(new GalleryImageFeature()
586+
.withName(FEATURE_SECURITY_TYPE)
587+
.withValue(SecurityTypes.TRUSTED_LAUNCH.toString()))
588+
).collect(Collectors.toList())
589+
);
582590
return this;
583591
}
584592

sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/models/GalleryImage.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public interface GalleryImage
8383
/** @return the hypervisor generation. */
8484
HyperVGeneration hyperVGeneration();
8585

86-
/** @return the security type, whether trusted l. */
86+
/** @return the security type, whether trusted launch or confidential VM. */
8787
SecurityTypes securityType();
8888

8989
/** @return the tags associated with the image. */

sdk/resourcemanager/azure-resourcemanager-compute/src/main/java/com/azure/resourcemanager/compute/models/KnownWindowsVirtualMachineImage.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,16 @@ public enum KnownWindowsVirtualMachineImage {
1414
/** Windows Server 2016 Data center. */
1515
WINDOWS_SERVER_2016_DATACENTER("MicrosoftWindowsServer", "WindowsServer", "2016-Datacenter"),
1616
/** Windows Server 2012 R2 Data center. */
17-
WINDOWS_SERVER_2012_R2_DATACENTER("MicrosoftWindowsServer", "WindowsServer", "2012-R2-Datacenter");
17+
WINDOWS_SERVER_2012_R2_DATACENTER("MicrosoftWindowsServer", "WindowsServer", "2012-R2-Datacenter"),
18+
/** Windows Server 2019 Data center gen2. */
19+
WINDOWS_SERVER_2019_DATACENTER_GEN2("MicrosoftWindowsServer", "WindowsServer", "2019-datacenter-gensecond"),
20+
/** Windows Server 2019 Data center with containers gen2. */
21+
WINDOWS_SERVER_2019_DATACENTER_WITH_CONTAINERS_GEN2(
22+
"MicrosoftWindowsServer", "WindowsServer", "2019-datacenter-with-containers-g2"),
23+
/** Windows Server 2016 Data center gen2. */
24+
WINDOWS_SERVER_2016_DATACENTER_GEN2("MicrosoftWindowsServer", "WindowsServer", "2016-datacenter-gensecond"),
25+
/** Windows 10 2021 H2 Pro gen2. */
26+
WINDOWS_DESKTOP_10_21H2_PRO_GEN2("MicrosoftWindowsDesktop", "Windows-10", "win10-21h2-pro-g2");
1827

1928
private final String publisher;
2029
private final String offer;

sdk/resourcemanager/azure-resourcemanager-samples/samples.json

+6
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,12 @@
852852
"filePath": "azure-resourcemanager-samples/src/main/java/com/azure/resourcemanager/compute/samples/CloneVirtualMachineToNewRegion.java",
853853
"githubPath": "Azure-Samples/compute-java-clone-virtual-machine-to-new-region",
854854
"description": "Getting started on cloning virtual machine to a new region using Java"
855+
},
856+
{
857+
"owner": "ArthurMa1978",
858+
"filePath": "azure-resourcemanager-samples/src/main/java/com/azure/resourcemanager/compute/samples/CreateVirtualMachineWithTrustedLaunchFromGalleryImage.java",
859+
"githubPath": "Azure-Samples/compute-java-create-virtual-machine-with-trusted-launch-from-gallery-image",
860+
"description": "Getting started on creating virtual machine with trusted launch from gallery image using Java"
855861
}
856862
]
857863
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.resourcemanager.compute.samples;
5+
6+
import com.azure.core.credential.TokenCredential;
7+
import com.azure.core.http.policy.HttpLogDetailLevel;
8+
import com.azure.core.management.AzureEnvironment;
9+
import com.azure.core.management.Region;
10+
import com.azure.core.management.profile.AzureProfile;
11+
import com.azure.identity.DefaultAzureCredentialBuilder;
12+
import com.azure.resourcemanager.AzureResourceManager;
13+
import com.azure.resourcemanager.compute.models.CachingTypes;
14+
import com.azure.resourcemanager.compute.models.Gallery;
15+
import com.azure.resourcemanager.compute.models.GalleryDataDiskImage;
16+
import com.azure.resourcemanager.compute.models.GalleryImage;
17+
import com.azure.resourcemanager.compute.models.GalleryImageVersion;
18+
import com.azure.resourcemanager.compute.models.HyperVGeneration;
19+
import com.azure.resourcemanager.compute.models.HyperVGenerationTypes;
20+
import com.azure.resourcemanager.compute.models.KnownWindowsVirtualMachineImage;
21+
import com.azure.resourcemanager.compute.models.OperatingSystemStateTypes;
22+
import com.azure.resourcemanager.compute.models.RunCommandInput;
23+
import com.azure.resourcemanager.compute.models.VirtualMachine;
24+
import com.azure.resourcemanager.compute.models.VirtualMachineCustomImage;
25+
import com.azure.resourcemanager.compute.models.VirtualMachineDataDisk;
26+
import com.azure.resourcemanager.compute.models.VirtualMachineSizeTypes;
27+
import com.azure.resourcemanager.resources.models.ResourceGroup;
28+
import com.azure.resourcemanager.samples.Utils;
29+
30+
import java.util.Arrays;
31+
32+
/**
33+
* Azure Compute sample for creating virtual machine with TrustedLaunch from gallery image.
34+
* - Create a managed virtual machine with TrustedLaunch from PIR windows image with two empty data disks
35+
* - Prepare virtual machine for generalization
36+
* - Deallocate virtual machine
37+
* - Generalize virtual machine
38+
* - Create a virtual machine custom image from the created virtual machine
39+
* - Create a gallery to hold gallery images
40+
* - Create a gallery image in the gallery with hypervisor generation 2 and with TrustedLaunch feature
41+
* - Create a gallery image version from the virtual machine custom image
42+
* - Create a virtual machine with TrustedLaunch from the gallery image version
43+
*/
44+
public class CreateVirtualMachineWithTrustedLaunchFromGalleryImage {
45+
/**
46+
* Main function which runs the actual sample.
47+
* @param azure instance of the azure client
48+
* @return true if sample runs successfully
49+
*/
50+
public static boolean runSample(AzureResourceManager azure) {
51+
final String rgName = Utils.randomResourceName(azure, "rg", 15);
52+
final Region region = Region.US_WEST;
53+
final String newRgName = Utils.randomResourceName(azure, "rg", 15);
54+
final Region newRegion = Region.US_WEST2;
55+
56+
ResourceGroup resourceGroup = null;
57+
ResourceGroup newResourceGroup = null;
58+
try {
59+
resourceGroup = azure.resourceGroups()
60+
.define(rgName)
61+
.withRegion(region)
62+
.create();
63+
newResourceGroup = azure.resourceGroups()
64+
.define(newRgName)
65+
.withRegion(newRegion)
66+
.create();
67+
68+
//=============================================================
69+
// Create a managed virtual machine with TrustedLaunch from PIR image with two empty data disks
70+
final String trustedVmName = Utils.randomResourceName(azure, "vm", 15);
71+
VirtualMachine trustedVMFromPirImage = azure
72+
.virtualMachines()
73+
.define(trustedVmName)
74+
.withRegion(resourceGroup.region())
75+
.withExistingResourceGroup(resourceGroup)
76+
.withNewPrimaryNetwork("10.0.0.0/28")
77+
.withPrimaryPrivateIPAddressDynamic()
78+
.withoutPrimaryPublicIPAddress()
79+
.withPopularWindowsImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2016_DATACENTER_GEN2)
80+
.withAdminUsername("azureuser")
81+
.withAdminPassword(Utils.password())
82+
.withNewDataDisk(10)
83+
.withNewDataDisk(10, 2, CachingTypes.READ_WRITE)
84+
.withSize(VirtualMachineSizeTypes.STANDARD_DS1_V2)
85+
// Trusted Launch options start
86+
.withTrustedLaunch()
87+
.withSecureBoot()
88+
.withVTpm()
89+
// Trusted Launch options end
90+
.create();
91+
92+
Utils.print(trustedVMFromPirImage);
93+
94+
//=============================================================
95+
// Prepare virtual machine for generalization
96+
prepareWindowsVMForGeneralization(trustedVMFromPirImage);
97+
98+
//=============================================================
99+
// Deallocate virtual machine
100+
trustedVMFromPirImage.deallocate();
101+
102+
//=============================================================
103+
// Generalize virtual machine
104+
trustedVMFromPirImage.generalize();
105+
106+
//=============================================================
107+
// Create a virtual machine custom image
108+
final String imageName = Utils.randomResourceName(azure, "img", 20);
109+
VirtualMachineCustomImage.DefinitionStages.WithCreateAndDataDiskImageOSDiskSettings creatableDisk =
110+
azure.virtualMachineCustomImages()
111+
.define(imageName)
112+
.withRegion(resourceGroup.region())
113+
.withExistingResourceGroup(resourceGroup)
114+
.withHyperVGeneration(HyperVGenerationTypes.V2)
115+
.withWindowsFromDisk(trustedVMFromPirImage.osDiskId(), OperatingSystemStateTypes.GENERALIZED)
116+
.withOSDiskCaching(trustedVMFromPirImage.osDiskCachingType());
117+
118+
for (VirtualMachineDataDisk dataDisk : trustedVMFromPirImage.dataDisks().values()) {
119+
creatableDisk.defineDataDiskImage()
120+
.withLun(dataDisk.lun())
121+
.fromManagedDisk(dataDisk.id())
122+
.withDiskCaching(dataDisk.cachingType())
123+
.withDiskSizeInGB(dataDisk.size())
124+
.attach();
125+
}
126+
127+
VirtualMachineCustomImage customImage = creatableDisk.create();
128+
Utils.print(customImage);
129+
130+
//=============================================================
131+
// Create a gallery to hold gallery images
132+
final String galleryName = Utils.randomResourceName(azure, "jsim", 15);
133+
Gallery gallery = azure
134+
.galleries()
135+
.define(galleryName)
136+
.withRegion(Region.US_WEST_CENTRAL)
137+
.withExistingResourceGroup(resourceGroup)
138+
.withDescription("java's image gallery")
139+
.create();
140+
141+
//=============================================================
142+
// Create a gallery image in the gallery with hypervisor generation 2 and with TrustedLaunch feature
143+
final String galleryImageName = "SampleImages";
144+
GalleryImage galleryImage = azure
145+
.galleryImages()
146+
.define(galleryImageName)
147+
.withExistingGallery(gallery)
148+
.withLocation(resourceGroup.region())
149+
.withIdentifier("JavaSDKTeam", "JDK", "Jdk-9")
150+
.withGeneralizedWindows()
151+
.withHyperVGeneration(HyperVGeneration.V2)
152+
.withTrustedLaunch()
153+
.create();
154+
155+
//=============================================================
156+
// Create a gallery image version from the virtual machine custom image
157+
final String versionName = "0.0.1";
158+
GalleryImageVersion imageVersion = azure
159+
.galleryImageVersions()
160+
.define(versionName)
161+
.withExistingImage(resourceGroup.name(), gallery.name(), galleryImage.name())
162+
.withLocation(resourceGroup.region())
163+
.withSourceCustomImage(customImage)
164+
.withRegionAvailability(newRegion, 1)
165+
.create();
166+
167+
//=============================================================
168+
// Create a virtual machine with TrustedLaunch from the gallery image version
169+
final String vmFromImageName = Utils.randomResourceName(azure, "tlvm", 15);
170+
VirtualMachine.DefinitionStages.WithManagedCreate withManagedCreate =
171+
azure
172+
.virtualMachines()
173+
.define(vmFromImageName)
174+
.withRegion(newRegion)
175+
.withExistingResourceGroup(newResourceGroup)
176+
.withNewPrimaryNetwork("10.0.1.0/28")
177+
.withPrimaryPrivateIPAddressDynamic()
178+
.withoutPrimaryPublicIPAddress()
179+
.withGeneralizedWindowsGalleryImageVersion(imageVersion.id())
180+
.withAdminUsername("jvuser")
181+
.withAdminPassword(Utils.password());
182+
183+
for (GalleryDataDiskImage ddi : imageVersion.storageProfile().dataDiskImages()) {
184+
withManagedCreate.withNewDataDiskFromImage(
185+
ddi.lun(),
186+
ddi.sizeInGB() + 1,
187+
ddi.hostCaching() == null ? null : CachingTypes.fromString(ddi.hostCaching().toString()));
188+
}
189+
190+
VirtualMachine trustedVMFromGalleryImage = withManagedCreate
191+
.withSize(VirtualMachineSizeTypes.STANDARD_DS1_V2)
192+
// gallery images with 'TrustedLaunch` feature can only create VMs with 'TrustedLaunch' feature
193+
.withTrustedLaunch()
194+
.withSecureBoot()
195+
.withVTpm()
196+
.create();
197+
Utils.print(trustedVMFromGalleryImage);
198+
199+
return true;
200+
} catch (Exception e) {
201+
e.printStackTrace();
202+
return false;
203+
} finally {
204+
if (resourceGroup != null) {
205+
azure.resourceGroups().beginDeleteByName(rgName);
206+
}
207+
if (newResourceGroup != null) {
208+
azure.resourceGroups().beginDeleteByName(newRgName);
209+
}
210+
}
211+
}
212+
213+
//https://learn.microsoft.com/en-us/azure/virtual-machines/generalize#windows
214+
private static void prepareWindowsVMForGeneralization(VirtualMachine virtualMachine) {
215+
System.out.println("Trying to de-provision");
216+
virtualMachine.manager()
217+
.serviceClient()
218+
.getVirtualMachines()
219+
.beginRunCommand(
220+
virtualMachine.resourceGroupName(), virtualMachine.name(),
221+
new RunCommandInput()
222+
.withCommandId("RunPowerShellScript")
223+
.withScript(Arrays.asList(
224+
"Remove-Item 'C:\\Windows\\Panther' -Recurse",
225+
"& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /mode:vm /shutdown"
226+
)))
227+
.waitForCompletion();
228+
System.out.println("De-provision finished");
229+
}
230+
231+
/**
232+
* Main entry point.
233+
* @param args the parameters
234+
*/
235+
public static void main(String[] args) {
236+
try {
237+
//=============================================================
238+
// Authenticate
239+
240+
final AzureProfile profile = new AzureProfile(AzureEnvironment.AZURE);
241+
final TokenCredential credential = new DefaultAzureCredentialBuilder()
242+
.authorityHost(profile.getEnvironment().getActiveDirectoryEndpoint())
243+
.build();
244+
245+
AzureResourceManager azureResourceManager = AzureResourceManager
246+
.configure()
247+
.withLogLevel(HttpLogDetailLevel.BASIC)
248+
.authenticate(credential, profile)
249+
.withDefaultSubscription();
250+
251+
// Print selected subscription
252+
System.out.println("Selected subscription: " + azureResourceManager.subscriptionId());
253+
254+
runSample(azureResourceManager);
255+
} catch (Exception e) {
256+
System.out.println(e.getMessage());
257+
e.printStackTrace();
258+
}
259+
}
260+
}

sdk/resourcemanager/azure-resourcemanager-samples/src/main/java/com/azure/resourcemanager/samples/Utils.java

+6
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,11 @@ public static void print(VirtualMachine resource) {
500500
StringBuilder zones = new StringBuilder().append("\n\tZones: ");
501501
zones.append(resource.availabilityZones());
502502

503+
StringBuilder securityProfile = new StringBuilder().append("\n\tSecurityProfile: ");
504+
securityProfile.append("\n\t\t\tSecurity type: ").append(resource.securityType());
505+
securityProfile.append("\n\t\t\tSecure Boot enabled: ").append(resource.isSecureBootEnabled());
506+
securityProfile.append("\n\t\t\tvTPM enabled: ").append(resource.isVTpmEnabled());
507+
503508
System.out.println(new StringBuilder().append("Virtual Machine: ").append(resource.id())
504509
.append("Name: ").append(resource.name())
505510
.append("\n\tResource group: ").append(resource.resourceGroupName())
@@ -513,6 +518,7 @@ public static void print(VirtualMachine resource) {
513518
.append(extensions)
514519
.append(msi)
515520
.append(zones)
521+
.append(securityProfile)
516522
.toString());
517523
}
518524

sdk/resourcemanager/azure-resourcemanager-samples/src/test/java/com/azure/resourcemanager/samples/ComputeSampleTests.java

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.azure.resourcemanager.compute.samples.CreateVirtualMachineUsingCustomImageFromVM;
1212
import com.azure.resourcemanager.compute.samples.CreateVirtualMachineUsingSpecializedDiskFromSnapshot;
1313
import com.azure.resourcemanager.compute.samples.CreateVirtualMachineUsingSpecializedDiskFromVhd;
14+
import com.azure.resourcemanager.compute.samples.CreateVirtualMachineWithTrustedLaunchFromGalleryImage;
1415
import com.azure.resourcemanager.compute.samples.CreateVirtualMachinesAsyncTrackingRelatedResources;
1516
import com.azure.resourcemanager.compute.samples.CreateVirtualMachinesInParallel;
1617
import com.azure.resourcemanager.compute.samples.CreateVirtualMachinesUsingCustomImageOrSpecializedVHD;
@@ -198,4 +199,9 @@ public void testCreateVirtualMachineEncryptedUsingCustomerManagedKey() {
198199
public void testCloneVirtualMachineToNewRegion() {
199200
Assertions.assertTrue(CloneVirtualMachineToNewRegion.runSample(azureResourceManager));
200201
}
202+
203+
@Test
204+
public void testCreateVirtualMachineWithTrustedLaunchFromGalleryImage() {
205+
Assertions.assertTrue(CreateVirtualMachineWithTrustedLaunchFromGalleryImage.runSample(azureResourceManager));
206+
}
201207
}

0 commit comments

Comments
 (0)