Skip to content

Commit 6bc8d73

Browse files
authored
mgmt, support ephemeral os disk in vmss (Azure#27728)
* feature add * nit, comment
1 parent 8d91802 commit 6bc8d73

File tree

7 files changed

+1157
-80
lines changed

7 files changed

+1157
-80
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Features Added
66

77
- Supported `virtualMachineSizeType()` in `VirtualMachineSize` as a typed alias of `name`.
8+
- Supported ephemeral OS disk in `VirtualMachineScaleSet`.
89

910
## 2.13.0 (2022-03-11)
1011

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

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
import com.azure.resourcemanager.compute.models.BootDiagnostics;
2222
import com.azure.resourcemanager.compute.models.CachingTypes;
2323
import com.azure.resourcemanager.compute.models.DiagnosticsProfile;
24+
import com.azure.resourcemanager.compute.models.DiffDiskOptions;
25+
import com.azure.resourcemanager.compute.models.DiffDiskPlacement;
26+
import com.azure.resourcemanager.compute.models.DiffDiskSettings;
2427
import com.azure.resourcemanager.compute.models.DiskCreateOptionTypes;
2528
import com.azure.resourcemanager.compute.models.ImageReference;
2629
import com.azure.resourcemanager.compute.models.KnownLinuxVirtualMachineImage;
@@ -379,6 +382,16 @@ public String osDiskName() {
379382
}
380383
}
381384

385+
@Override
386+
public boolean isEphemeralOSDisk() {
387+
return this.innerModel() != null
388+
&& this.innerModel().virtualMachineProfile() != null
389+
&& this.innerModel().virtualMachineProfile().storageProfile() != null
390+
&& this.innerModel().virtualMachineProfile().storageProfile().osDisk() != null
391+
&& this.innerModel().virtualMachineProfile().storageProfile().osDisk().diffDiskSettings() != null
392+
&& this.innerModel().virtualMachineProfile().storageProfile().osDisk().diffDiskSettings().placement() != null;
393+
}
394+
382395
@Override
383396
public UpgradeMode upgradeModel() {
384397
// flexible vmss won't have an upgrade mode
@@ -397,7 +410,7 @@ public VirtualMachineScaleSetSkuTypes sku() {
397410

398411
@Override
399412
public int capacity() {
400-
if (this.innerModel().sku() == null) {
413+
if (isVMProfileNotSet()) {
401414
return 0;
402415
}
403416
return ResourceManagerUtils.toPrimitiveInt(this.innerModel().sku().capacity());
@@ -1153,6 +1166,19 @@ public VirtualMachineScaleSetImpl withOSDiskName(String name) {
11531166
return this;
11541167
}
11551168

1169+
@Override
1170+
public VirtualMachineScaleSetImpl withEphemeralOSDisk() {
1171+
if (isVMProfileNotSet()) {
1172+
return this;
1173+
}
1174+
initVMProfileIfNecessary();
1175+
VirtualMachineScaleSetOSDisk disk = this.innerModel().virtualMachineProfile().storageProfile().osDisk();
1176+
disk.withCaching(CachingTypes.READ_ONLY);
1177+
disk.withDiffDiskSettings(new DiffDiskSettings());
1178+
disk.diffDiskSettings().withOption(DiffDiskOptions.LOCAL);
1179+
return this;
1180+
}
1181+
11561182
@Override
11571183
public VirtualMachineScaleSetImpl withComputerNamePrefix(String namePrefix) {
11581184
initVMProfileIfNecessary();
@@ -1610,7 +1636,7 @@ protected Mono<VirtualMachineScaleSetInner> createInner() {
16101636
// support flexible vmss with no profile
16111637
if (this.orchestrationMode() == OrchestrationMode.FLEXIBLE
16121638
// presence of sku indicates that the vm profile is not null, otherwise, vm profile is null.
1613-
&& this.innerModel().sku() == null) {
1639+
&& isVMProfileNotSet()) {
16141640
return createInnerNoProfile();
16151641
}
16161642
if (this.shouldSetProfileDefaults()) {
@@ -1725,9 +1751,14 @@ protected Mono<VirtualMachineScaleSetInner> getInnerAsync() {
17251751
}
17261752

17271753

1754+
17281755
// Helpers
17291756
//
17301757

1758+
private boolean isVMProfileNotSet() {
1759+
return this.innerModel().sku() == null;
1760+
}
1761+
17311762
private void adjustProfileForFlexibleMode() {
17321763
if (this.orchestrationMode() == OrchestrationMode.FLEXIBLE) {
17331764
if (this.innerModel().virtualMachineProfile().networkProfile().networkInterfaceConfigurations() != null) {
@@ -1748,6 +1779,7 @@ private void adjustProfileForFlexibleMode() {
17481779
.withNetworkApiVersion(NetworkApiVersion.TWO_ZERO_TWO_ZERO_ONE_ONE_ZERO_ONE);
17491780
}
17501781
}
1782+
17511783
private Mono<VirtualMachineScaleSetInner> createInnerNoProfile() {
17521784
this.innerModel().withVirtualMachineProfile(null);
17531785
return manager()
@@ -2955,6 +2987,12 @@ public VirtualMachineScaleSetImpl withPlan(PurchasePlan plan) {
29552987
return this;
29562988
}
29572989

2990+
@Override
2991+
public VirtualMachineScaleSetImpl withPlacement(DiffDiskPlacement placement) {
2992+
this.innerModel().virtualMachineProfile().storageProfile().osDisk().diffDiskSettings().withPlacement(placement);
2993+
return this;
2994+
}
2995+
29582996
/**
29592997
* Class to manage Data Disk collection.
29602998
*/

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ interface WithOSDiskSettings {
12191219
WithEphemeralOSDisk withEphemeralOSDisk();
12201220
}
12211221

1222-
/** The stage of a virtual machine definition allowing to select Ephemeral OS disk placement. */
1222+
/** The stage of a virtual machine definition allowing to set OS disk to be ephemeral. */
12231223
interface WithEphemeralOSDisk {
12241224
/**
12251225
* Selects where you want to place the Ephemeral OS disk.

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ Mono<RunCommandResult> runShellScriptInVMInstanceAsync(
174174
/** @return the name of the OS disk of virtual machines in the scale set */
175175
String osDiskName();
176176

177+
/** @return whether the instance OS disk is ephemeral */
178+
boolean isEphemeralOSDisk();
179+
177180
/** @return the upgrade model, null for scale set with {@link OrchestrationMode#FLEXIBLE} */
178181
UpgradeMode upgradeModel();
179182

@@ -1371,6 +1374,13 @@ interface WithOSDiskSettings {
13711374
* @return the next stage of the definition
13721375
*/
13731376
WithCreate withOSDiskName(String name);
1377+
1378+
/**
1379+
* Specifies the OS disk to be ephemeral.
1380+
*
1381+
* @return the next stage of the definition
1382+
*/
1383+
WithEphemeralOSDisk withEphemeralOSDisk();
13741384
}
13751385

13761386
/** The stage of a virtual machine scale set definition allowing to specify the storage account. */
@@ -1762,6 +1772,18 @@ interface WithPlan {
17621772
WithCreate withPlan(PurchasePlan plan);
17631773
}
17641774

1775+
/**
1776+
* The stage of the virtual machine scale set definition allowing to configure instance OS disk to be ephemeral.
1777+
*/
1778+
interface WithEphemeralOSDisk {
1779+
/**
1780+
* Selects where you want to place the Ephemeral OS disk.
1781+
* @param placement placement of the Ephemeral OS disk
1782+
* @return the next stage of the definition
1783+
*/
1784+
WithManagedCreate withPlacement(DiffDiskPlacement placement);
1785+
}
1786+
17651787
/**
17661788
* The stage of a virtual machine scale set definition containing all the required inputs for the resource to be
17671789
* created, but also allowing for any other optional settings to be specified.
@@ -1790,6 +1812,7 @@ interface WithCreate
17901812
DefinitionStages.WithApplicationSecurityGroup,
17911813
DefinitionStages.WithSecrets,
17921814
DefinitionStages.WithPlan,
1815+
DefinitionStages.WithEphemeralOSDisk,
17931816
Resource.DefinitionWithTags<VirtualMachineScaleSet.DefinitionStages.WithCreate> {
17941817
}
17951818
}

sdk/resourcemanager/azure-resourcemanager-compute/src/test/java/com/azure/resourcemanager/compute/VirtualMachineScaleSetOperationsTests.java

Lines changed: 112 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import com.azure.resourcemanager.authorization.models.BuiltInRole;
1212
import com.azure.resourcemanager.authorization.models.RoleAssignment;
1313
import com.azure.resourcemanager.compute.fluent.models.VirtualMachineScaleSetInner;
14+
import com.azure.resourcemanager.compute.models.DeleteOptions;
15+
import com.azure.resourcemanager.compute.models.DiffDiskPlacement;
1416
import com.azure.resourcemanager.compute.models.ImageReference;
1517
import com.azure.resourcemanager.compute.models.KnownLinuxVirtualMachineImage;
1618
import com.azure.resourcemanager.compute.models.OperatingSystemTypes;
@@ -22,6 +24,7 @@
2224
import com.azure.resourcemanager.compute.models.UpgradeMode;
2325
import com.azure.resourcemanager.compute.models.VaultCertificate;
2426
import com.azure.resourcemanager.compute.models.VaultSecretGroup;
27+
import com.azure.resourcemanager.compute.models.VirtualMachine;
2528
import com.azure.resourcemanager.compute.models.VirtualMachineEvictionPolicyTypes;
2629
import com.azure.resourcemanager.compute.models.VirtualMachineImage;
2730
import com.azure.resourcemanager.compute.models.VirtualMachinePriorityTypes;
@@ -32,6 +35,7 @@
3235
import com.azure.resourcemanager.compute.models.VirtualMachineScaleSetVM;
3336
import com.azure.resourcemanager.compute.models.VirtualMachineScaleSetVMExpandType;
3437
import com.azure.resourcemanager.compute.models.VirtualMachineScaleSetVMs;
38+
import com.azure.resourcemanager.compute.models.VirtualMachineSizeTypes;
3539
import com.azure.resourcemanager.keyvault.models.Secret;
3640
import com.azure.resourcemanager.keyvault.models.Vault;
3741
import com.azure.resourcemanager.network.models.ApplicationSecurityGroup;
@@ -59,14 +63,17 @@
5963
import org.junit.jupiter.api.Test;
6064

6165
import java.io.InputStream;
66+
import java.lang.reflect.Method;
6267
import java.nio.charset.StandardCharsets;
6368
import java.time.Duration;
6469
import java.util.ArrayList;
6570
import java.util.Arrays;
6671
import java.util.Collection;
6772
import java.util.Collections;
73+
import java.util.HashSet;
6874
import java.util.List;
6975
import java.util.Map;
76+
import java.util.Set;
7077
import java.util.stream.Collectors;
7178

7279
public class VirtualMachineScaleSetOperationsTests extends ComputeManagementTest {
@@ -1741,53 +1748,18 @@ public void npeProtectionTest() throws Exception {
17411748
.withFlexibleOrchestrationMode()
17421749
.create();
17431750

1744-
vmss.orchestrationMode();
1745-
vmss.computerNamePrefix();
1746-
vmss.osType();
1747-
vmss.osDiskCachingType();
1748-
vmss.osDiskName();
1749-
vmss.upgradeModel();
1750-
vmss.overProvisionEnabled();
1751-
vmss.sku();
1752-
vmss.capacity();
1753-
vmss.getPrimaryNetwork();
1754-
vmss.getPrimaryInternetFacingLoadBalancer();
1755-
vmss.listPrimaryInternetFacingLoadBalancerBackends();
1756-
vmss.listPrimaryInternetFacingLoadBalancerInboundNatPools();
1757-
vmss.getPrimaryInternalLoadBalancer();
1758-
vmss.listPrimaryInternalLoadBalancerBackends();
1759-
vmss.listPrimaryInternalLoadBalancerInboundNatPools();
1760-
vmss.primaryPublicIpAddressIds();
1761-
vmss.vhdContainers();
1762-
vmss.storageProfile();
1763-
vmss.networkProfile();
1764-
vmss.extensions();
1765-
vmss.virtualMachinePriority();
1766-
vmss.billingProfile();
1767-
vmss.plan();
1768-
vmss.virtualMachineEvictionPolicy();
1769-
vmss.listNetworkInterfaces();
1770-
vmss.isManagedDiskEnabled();
1771-
vmss.isManagedServiceIdentityEnabled();
1772-
vmss.systemAssignedManagedServiceIdentityTenantId();
1773-
vmss.systemAssignedManagedServiceIdentityPrincipalId();
1774-
vmss.managedServiceIdentityType();
1775-
vmss.userAssignedManagedServiceIdentityIds();
1776-
vmss.availabilityZones();
1777-
vmss.isBootDiagnosticsEnabled();
1778-
vmss.bootDiagnosticsStorageUri();
1779-
vmss.managedOSDiskStorageAccountType();
1780-
vmss.virtualMachinePublicIpConfig();
1781-
vmss.isIpForwardingEnabled();
1782-
vmss.isAcceleratedNetworkingEnabled();
1783-
vmss.networkSecurityGroupId();
1784-
vmss.isSinglePlacementGroupEnabled();
1785-
vmss.applicationGatewayBackendAddressPoolsIds();
1786-
vmss.applicationSecurityGroupIds();
1787-
vmss.doNotRunExtensionsOnOverprovisionedVMs();
1788-
vmss.proximityPlacementGroup();
1789-
vmss.additionalCapabilities();
1790-
vmss.orchestrationMode();
1751+
String excludeMethodsString = "start,startAsync,reimage,reimageAsync,deallocate,deallocateAsync,powerOff,powerOffAsync,restart,restartAsync";
1752+
Set<String> excludeMethods = new HashSet<>(Arrays.asList(excludeMethodsString.split(",")));
1753+
Set<String> invoked = new HashSet<>();
1754+
// invoke all the methods with 0 parameters except those from the exclusion set
1755+
for (Method method : VirtualMachineScaleSet.class.getDeclaredMethods()) {
1756+
if (!excludeMethods.contains(method.getName()) && method.getParameterCount() == 0) {
1757+
method.invoke(vmss);
1758+
invoked.add(method.getName());
1759+
}
1760+
}
1761+
Assertions.assertTrue(invoked.contains("isEphemeralOSDisk"));
1762+
Assertions.assertFalse(invoked.contains("start"));
17911763
}
17921764

17931765
@Test
@@ -1850,4 +1822,97 @@ public void canBatchOperateVMSSInstance() {
18501822
VirtualMachineScaleSetVM vmInstance1 = vmss.virtualMachines().getInstance("1");
18511823
Assertions.assertEquals(PowerState.RUNNING, vmInstance1.powerState());
18521824
}
1825+
1826+
@Test
1827+
public void canCreateVMSSWithEphemeralOSDisk() throws Exception {
1828+
// uniform vmss with ephemeral os disk
1829+
final String vmssName = generateRandomResourceName("vmss", 10);
1830+
1831+
Network network = this.networkManager
1832+
.networks()
1833+
.define("vmssvnet")
1834+
.withRegion(region)
1835+
.withNewResourceGroup(rgName)
1836+
.withAddressSpace("10.0.0.0/28")
1837+
.withSubnet("subnet1", "10.0.0.0/28")
1838+
.create();
1839+
1840+
VirtualMachineScaleSet uniformVMSS = this.computeManager
1841+
.virtualMachineScaleSets()
1842+
.define(vmssName)
1843+
.withRegion(region)
1844+
.withExistingResourceGroup(rgName)
1845+
.withSku(VirtualMachineScaleSetSkuTypes.STANDARD_DS1_V2)
1846+
.withExistingPrimaryNetworkSubnet(network, "subnet1")
1847+
.withoutPrimaryInternetFacingLoadBalancer()
1848+
.withoutPrimaryInternalLoadBalancer()
1849+
.withPopularLinuxImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_18_04_LTS)
1850+
.withRootUsername("jvuser")
1851+
.withSsh(sshPublicKey())
1852+
.withUpgradeMode(UpgradeMode.AUTOMATIC)
1853+
.withEphemeralOSDisk()
1854+
.withPlacement(DiffDiskPlacement.CACHE_DISK)
1855+
.withCapacity(2)
1856+
.create();
1857+
Assertions.assertTrue(uniformVMSS.isEphemeralOSDisk());
1858+
1859+
// flex vmss with ephemeral os disk
1860+
Network network2 =
1861+
this
1862+
.networkManager
1863+
.networks()
1864+
.define("vmssvnet2")
1865+
.withRegion(region)
1866+
.withExistingResourceGroup(rgName)
1867+
.withAddressSpace("10.1.0.0/16")
1868+
.withSubnet("subnet1", "10.1.0.0/16")
1869+
.create();
1870+
LoadBalancer publicLoadBalancer = createHttpLoadBalancers(region, this.resourceManager.resourceGroups().getByName(rgName), "1", LoadBalancerSkuType.STANDARD, PublicIPSkuType.STANDARD, true);
1871+
1872+
final String vmssName1 = generateRandomResourceName("vmss", 10);
1873+
VirtualMachineScaleSet flexVMSS = this.computeManager
1874+
.virtualMachineScaleSets()
1875+
.define(vmssName1)
1876+
.withRegion(region)
1877+
.withNewResourceGroup(rgName)
1878+
.withFlexibleOrchestrationMode()
1879+
.withSku(VirtualMachineScaleSetSkuTypes.STANDARD_DS1_V2)
1880+
.withExistingPrimaryNetworkSubnet(network2, "subnet1")
1881+
.withExistingPrimaryInternetFacingLoadBalancer(publicLoadBalancer)
1882+
.withoutPrimaryInternalLoadBalancer()
1883+
.withPopularLinuxImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_16_04_LTS)
1884+
.withRootUsername("jvuser")
1885+
.withSsh(sshPublicKey())
1886+
.withEphemeralOSDisk()
1887+
.withPlacement(DiffDiskPlacement.CACHE_DISK)
1888+
.create();
1889+
Assertions.assertTrue(flexVMSS.isEphemeralOSDisk());
1890+
VirtualMachine instance1 = this.computeManager
1891+
.virtualMachines()
1892+
.getById(flexVMSS.virtualMachines().list().stream().iterator().next().id());
1893+
Assertions.assertTrue(instance1.isOSDiskEphemeral());
1894+
1895+
// can add vm with non-ephemeral os disk to flex vmss with ephemeral os disk vm profile
1896+
final String vmName = generateRandomResourceName("vm", 10);
1897+
VirtualMachine vm = this.computeManager
1898+
.virtualMachines()
1899+
.define(vmName)
1900+
.withRegion(region)
1901+
.withNewResourceGroup(rgName)
1902+
.withExistingPrimaryNetwork(network2)
1903+
.withSubnet("subnet1")
1904+
.withPrimaryPrivateIPAddressDynamic()
1905+
.withoutPrimaryPublicIPAddress()
1906+
.withPopularLinuxImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_18_04_LTS)
1907+
.withRootUsername("Foo12")
1908+
.withSsh(sshPublicKey())
1909+
.withSize(VirtualMachineSizeTypes.STANDARD_DS1_V2)
1910+
.withPrimaryNetworkInterfaceDeleteOptions(DeleteOptions.DELETE)
1911+
.withExistingVirtualMachineScaleSet(flexVMSS)
1912+
.create();
1913+
Assertions.assertEquals(vm.virtualMachineScaleSetId(), flexVMSS.id());
1914+
// flex vmss can have a mixed set of VMs with ephemeral and non-ephemeral os disk
1915+
// which contradicts the FAQ: https://docs.microsoft.com/en-us/azure/virtual-machines/ephemeral-os-disks#frequently-asked-questions
1916+
Assertions.assertFalse(vm.isOSDiskEphemeral());
1917+
}
18531918
}

0 commit comments

Comments
 (0)