Skip to content

Commit 04f9b83

Browse files
authored
mgmt compute, support updating deleteOptions for VM (Azure#36308)
* test case * interface * implementation, add support for newly attached disks or nics * assets.json * changelog * checkstyle * minor fix on withNetworkInterfacesDeleteOptions * test comments * modify batch update to support updateByIds checkstyle * assets.json * fix testCompile issue * update according to comments
1 parent 2d6d2d6 commit 04f9b83

File tree

5 files changed

+247
-5
lines changed

5 files changed

+247
-5
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Features Added
66

7+
- Supported updating delete options for OS disk, data disks and network interfaces attached to `VirtualMachine`.
8+
79
### Breaking Changes
810

911
### Bugs Fixed

sdk/resourcemanager/azure-resourcemanager-compute/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "java",
44
"TagPrefix": "java/resourcemanager/azure-resourcemanager-compute",
5-
"Tag": "java/resourcemanager/azure-resourcemanager-compute_971172d297"
5+
"Tag": "java/resourcemanager/azure-resourcemanager-compute_32d18bac37"
66
}

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

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.azure.core.management.provider.IdentifierProvider;
1010
import com.azure.core.management.serializer.SerializerFactory;
1111
import com.azure.core.util.Context;
12+
import com.azure.core.util.CoreUtils;
1213
import com.azure.core.util.logging.ClientLogger;
1314
import com.azure.core.util.serializer.SerializerAdapter;
1415
import com.azure.core.util.serializer.SerializerEncoding;
@@ -110,14 +111,18 @@
110111
import java.net.URL;
111112
import java.time.OffsetDateTime;
112113
import java.util.ArrayList;
114+
import java.util.Arrays;
113115
import java.util.Collections;
114116
import java.util.HashMap;
115117
import java.util.HashSet;
116118
import java.util.List;
119+
import java.util.Locale;
117120
import java.util.Map;
121+
import java.util.Objects;
118122
import java.util.Set;
119123
import java.util.UUID;
120124
import java.util.concurrent.Callable;
125+
import java.util.stream.Collectors;
121126

122127
/** The implementation for VirtualMachine and its create and update interfaces. */
123128
class VirtualMachineImpl
@@ -1998,6 +2003,28 @@ public OffsetDateTime timeCreated() {
19982003
return innerModel().timeCreated();
19992004
}
20002005

2006+
@Override
2007+
public DeleteOptions primaryNetworkInterfaceDeleteOptions() {
2008+
String nicId = primaryNetworkInterfaceId();
2009+
return networkInterfaceDeleteOptions(nicId);
2010+
}
2011+
2012+
@Override
2013+
public DeleteOptions networkInterfaceDeleteOptions(String networkInterfaceId) {
2014+
if (CoreUtils.isNullOrEmpty(networkInterfaceId)
2015+
|| this.innerModel().networkProfile() == null
2016+
|| this.innerModel().networkProfile().networkInterfaces() == null) {
2017+
return null;
2018+
}
2019+
return this.innerModel().networkProfile()
2020+
.networkInterfaces()
2021+
.stream()
2022+
.filter(nic -> networkInterfaceId.equalsIgnoreCase(nic.id()))
2023+
.findAny()
2024+
.map(NetworkInterfaceReference::deleteOption)
2025+
.orElse(null);
2026+
}
2027+
20012028
@Override
20022029
public VirtualMachinePriorityTypes priority() {
20032030
return this.innerModel().priority();
@@ -2175,6 +2202,7 @@ private void reset(VirtualMachineInner inner) {
21752202
creatableSecondaryNetworkInterfaceKeys.clear();
21762203
existingSecondaryNetworkInterfacesToAssociate.clear();
21772204
secondaryNetworkInterfaceDeleteOptions.clear();
2205+
primaryNetworkInterfaceDeleteOptions = null;
21782206
}
21792207

21802208
VirtualMachineImpl withUnmanagedDataDisk(UnmanagedDataDiskImpl dataDisk) {
@@ -2207,12 +2235,62 @@ public VirtualMachineImpl withAvailabilityZone(AvailabilityZoneId zoneId) {
22072235
return this;
22082236
}
22092237

2238+
@Override
2239+
public VirtualMachineImpl withOsDiskDeleteOptions(DeleteOptions deleteOptions) {
2240+
if (deleteOptions == null
2241+
|| this.innerModel().storageProfile() == null || this.innerModel().storageProfile().osDisk() == null) {
2242+
return null;
2243+
}
2244+
this.innerModel().storageProfile().osDisk().withDeleteOption(diskDeleteOptionsFromDeleteOptions(deleteOptions));
2245+
return this;
2246+
}
2247+
22102248
@Override
22112249
public VirtualMachineImpl withPrimaryNetworkInterfaceDeleteOptions(DeleteOptions deleteOptions) {
22122250
this.primaryNetworkInterfaceDeleteOptions = deleteOptions;
22132251
return this;
22142252
}
22152253

2254+
@Override
2255+
public VirtualMachineImpl withNetworkInterfacesDeleteOptions(DeleteOptions deleteOptions, String... nicIds) {
2256+
if (nicIds == null || nicIds.length == 0) {
2257+
throw new IllegalArgumentException("No nicIds specified for `withNetworkInterfacesDeleteOptions`");
2258+
}
2259+
if (this.innerModel().networkProfile() != null
2260+
&& this.innerModel().networkProfile().networkInterfaces() != null) {
2261+
Set<String> nicIdSet = Arrays.stream(nicIds).map(nicId -> nicId.toLowerCase(Locale.ROOT)).collect(Collectors.toSet());
2262+
this.innerModel().networkProfile().networkInterfaces().forEach(
2263+
nic -> {
2264+
if (nicIdSet.contains(nic.id().toLowerCase(Locale.ROOT))) {
2265+
nic.withDeleteOption(deleteOptions);
2266+
}
2267+
}
2268+
);
2269+
}
2270+
return this;
2271+
}
2272+
2273+
@Override
2274+
public VirtualMachineImpl withDataDisksDeleteOptions(DeleteOptions deleteOptions, Integer... luns) {
2275+
if (luns == null || luns.length == 0) {
2276+
throw new IllegalArgumentException("No luns specified for `withDataDisksDeleteOptions`");
2277+
}
2278+
Set<Integer> lunSet = Arrays.stream(luns).filter(Objects::nonNull).collect(Collectors.toSet());
2279+
if (lunSet.isEmpty()) {
2280+
throw new IllegalArgumentException("No non-null luns specified for `withDataDisksDeleteOptions`");
2281+
}
2282+
if (this.innerModel().storageProfile() != null && this.innerModel().storageProfile().dataDisks() != null) {
2283+
this.innerModel().storageProfile().dataDisks().forEach(
2284+
dataDisk -> {
2285+
if (lunSet.contains(dataDisk.lun())) {
2286+
dataDisk.withDeleteOption(diskDeleteOptionsFromDeleteOptions(deleteOptions));
2287+
}
2288+
}
2289+
);
2290+
}
2291+
return this;
2292+
}
2293+
22162294
AzureEnvironment environment() {
22172295
return manager().environment();
22182296
}
@@ -2397,13 +2475,20 @@ private void handleNetworkSettings() {
23972475
NetworkInterfaceReference nicReference = new NetworkInterfaceReference();
23982476
nicReference.withPrimary(true);
23992477
nicReference.withId(primaryNetworkInterface.id());
2400-
if (this.primaryNetworkInterfaceDeleteOptions != null) {
2401-
nicReference.withDeleteOption(this.primaryNetworkInterfaceDeleteOptions);
2402-
}
24032478
this.innerModel().networkProfile().networkInterfaces().add(nicReference);
24042479
}
24052480
}
24062481

2482+
// sets the delete options for primary network interface
2483+
if (this.primaryNetworkInterfaceDeleteOptions != null) {
2484+
String primaryNetworkInterfaceId = primaryNetworkInterfaceId();
2485+
if (primaryNetworkInterfaceId != null) {
2486+
this.innerModel().networkProfile().networkInterfaces().stream()
2487+
.filter(nic -> primaryNetworkInterfaceId.equals(nic.id()))
2488+
.forEach(nic -> nic.withDeleteOption(this.primaryNetworkInterfaceDeleteOptions));
2489+
}
2490+
}
2491+
24072492
// sets the virtual machine secondary network interfaces
24082493
//
24092494
for (String creatableSecondaryNetworkInterfaceKey : this.creatableSecondaryNetworkInterfaceKeys) {

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

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,21 @@ Mono<RunCommandResult> runShellScriptAsync(
426426
/** @return the time at which the Virtual Machine resource was created */
427427
OffsetDateTime timeCreated();
428428

429+
/**
430+
* Gets the delete options for the primary network interface.
431+
*
432+
* @return the delete options for the primary network interface
433+
*/
434+
DeleteOptions primaryNetworkInterfaceDeleteOptions();
435+
436+
/**
437+
* Gets the delete options for the given network interface.
438+
*
439+
* @param networkInterfaceId resource ID of the network interface
440+
* @return the delete options for the network interface
441+
*/
442+
DeleteOptions networkInterfaceDeleteOptions(String networkInterfaceId);
443+
429444
// Setters
430445
//
431446

@@ -2492,6 +2507,47 @@ interface WithSecurityFeatures {
24922507
*/
24932508
Update withoutVTpm();
24942509
}
2510+
2511+
/** The stage of the VM update allowing to change delete options of resources attached to this VM . */
2512+
interface WithDeleteOptions {
2513+
/**
2514+
* Specifies delete options for the OS disk of the VM.
2515+
*
2516+
* @param deleteOptions delete options for the OS disk
2517+
* @return the next stage of the update
2518+
*/
2519+
Update withOsDiskDeleteOptions(DeleteOptions deleteOptions);
2520+
2521+
/**
2522+
* Specifies delete options for the primary network interface of the VM.
2523+
*
2524+
* @param deleteOptions delete options for the primary network interface
2525+
* @return the next stage of the update
2526+
*/
2527+
Update withPrimaryNetworkInterfaceDeleteOptions(DeleteOptions deleteOptions);
2528+
2529+
/**
2530+
* Specifies delete options for the network interfaces attached to the VM.
2531+
* <p>This operation only affects existing <strong>attached</strong> network interfaces. Any newly-attached
2532+
* network interfaces that appear before {@link Update#apply()} won't be affected.</p>
2533+
*
2534+
* @param deleteOptions delete options for the network interfaces
2535+
* @param nicIds resource IDs of the network interfaces
2536+
* @return the next stage of the update
2537+
*/
2538+
Update withNetworkInterfacesDeleteOptions(DeleteOptions deleteOptions, String... nicIds);
2539+
2540+
/**
2541+
* Specifies delete options for the existing data disk attached to the VM.
2542+
* <p>This operation only affects existing <strong>attached</strong> data disks. Any newly-attached data disks
2543+
* that appear before {@link Update#apply()} won't be affected.</p>
2544+
*
2545+
* @param deleteOptions delete options for the data disk
2546+
* @param luns the disk LUNs to update
2547+
* @return the next stage of the update
2548+
*/
2549+
Update withDataDisksDeleteOptions(DeleteOptions deleteOptions, Integer... luns);
2550+
}
24952551
}
24962552

24972553
/** The template for an update operation, containing all the settings that can be modified. */
@@ -2510,7 +2566,8 @@ interface Update
25102566
UpdateStages.WithLicenseType,
25112567
UpdateStages.WithAdditionalCapacities,
25122568
UpdateStages.WithOSDisk,
2513-
UpdateStages.WithSecurityFeatures {
2569+
UpdateStages.WithSecurityFeatures,
2570+
UpdateStages.WithDeleteOptions {
25142571
/**
25152572
* Specifies the encryption settings for the OS Disk.
25162573
*

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

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.azure.resourcemanager.compute.models.SecurityTypes;
3333
import com.azure.resourcemanager.compute.models.UpgradeMode;
3434
import com.azure.resourcemanager.compute.models.VirtualMachine;
35+
import com.azure.resourcemanager.compute.models.VirtualMachineDiskOptions;
3536
import com.azure.resourcemanager.compute.models.VirtualMachineEvictionPolicyTypes;
3637
import com.azure.resourcemanager.compute.models.VirtualMachineInstanceView;
3738
import com.azure.resourcemanager.compute.models.VirtualMachinePriorityTypes;
@@ -1608,6 +1609,103 @@ public void canCRUDTrustedLaunchVM() {
16081609
computeManager.virtualMachines().deleteById(vm.id());
16091610
}
16101611

1612+
@Test
1613+
public void canUpdateDeleteOptions() {
1614+
String networkName = generateRandomResourceName("network", 15);
1615+
String nicName = generateRandomResourceName("nic", 15);
1616+
String nicName2 = generateRandomResourceName("nic", 15);
1617+
1618+
Network network = this
1619+
.networkManager
1620+
.networks()
1621+
.define(networkName)
1622+
.withRegion(region)
1623+
.withNewResourceGroup(rgName)
1624+
.withAddressSpace("10.0.1.0/24")
1625+
.withSubnet("subnet1", "10.0.1.0/28")
1626+
.withSubnet("subnet2", "10.0.1.16/28")
1627+
.create();
1628+
1629+
// OS disk, primary and secondary nics, data disk delete options all set to DELETE
1630+
VirtualMachine vm = computeManager.virtualMachines()
1631+
.define(vmName)
1632+
.withRegion(region)
1633+
.withNewResourceGroup(rgName)
1634+
.withExistingPrimaryNetwork(network)
1635+
.withSubnet("subnet1")
1636+
.withPrimaryPrivateIPAddressDynamic()
1637+
.withoutPrimaryPublicIPAddress()
1638+
.withPopularLinuxImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_20_04_LTS_GEN2)
1639+
.withRootUsername("Foo12")
1640+
.withSsh(sshPublicKey())
1641+
.withNewDataDisk(10, 1, new VirtualMachineDiskOptions().withDeleteOptions(DeleteOptions.DELETE))
1642+
.withSize(VirtualMachineSizeTypes.STANDARD_DS3_V2)
1643+
.withNewSecondaryNetworkInterface(this
1644+
.networkManager
1645+
.networkInterfaces()
1646+
.define(nicName)
1647+
.withRegion(region)
1648+
.withExistingResourceGroup(rgName)
1649+
.withExistingPrimaryNetwork(network)
1650+
.withSubnet("subnet1")
1651+
.withPrimaryPrivateIPAddressDynamic(), DeleteOptions.DELETE)
1652+
.withPrimaryNetworkInterfaceDeleteOptions(DeleteOptions.DELETE)
1653+
.withOSDiskDeleteOptions(DeleteOptions.DELETE)
1654+
.create();
1655+
1656+
Assertions.assertEquals(DeleteOptions.DELETE, vm.osDiskDeleteOptions());
1657+
Assertions.assertEquals(DeleteOptions.DELETE, vm.primaryNetworkInterfaceDeleteOptions());
1658+
Assertions.assertTrue(vm.dataDisks().values().stream().allMatch(disk -> DeleteOptions.DELETE.equals(disk.deleteOptions())));
1659+
1660+
// update delete options all to DETACH, except for secondary nic
1661+
vm.update()
1662+
.withOsDiskDeleteOptions(DeleteOptions.DETACH)
1663+
.withPrimaryNetworkInterfaceDeleteOptions(DeleteOptions.DETACH)
1664+
.withDataDisksDeleteOptions(DeleteOptions.DETACH, 1)
1665+
.apply();
1666+
1667+
Assertions.assertEquals(DeleteOptions.DETACH, vm.osDiskDeleteOptions());
1668+
Assertions.assertEquals(DeleteOptions.DETACH, vm.primaryNetworkInterfaceDeleteOptions());
1669+
// secondary nic delete options remains unchanged
1670+
Assertions.assertTrue(vm.networkInterfaceIds().stream()
1671+
.filter(nicId -> !nicId.equals(vm.primaryNetworkInterfaceId())).allMatch(nicId -> DeleteOptions.DELETE.equals(vm.networkInterfaceDeleteOptions(nicId))));
1672+
Assertions.assertTrue(vm.dataDisks().values().stream().allMatch(disk -> DeleteOptions.DETACH.equals(disk.deleteOptions())));
1673+
1674+
NetworkInterface secondaryNic2 =
1675+
this
1676+
.networkManager
1677+
.networkInterfaces()
1678+
.define(nicName2)
1679+
.withRegion(region)
1680+
.withExistingResourceGroup(rgName)
1681+
.withExistingPrimaryNetwork(network)
1682+
.withSubnet("subnet2")
1683+
.withPrimaryPrivateIPAddressDynamic()
1684+
.create();
1685+
1686+
vm.powerOff();
1687+
vm.deallocate();
1688+
1689+
// attach a new network interface and a new data disk, with delete options "DETACH"
1690+
vm.update()
1691+
.withNewDataDisk(1, 2, new VirtualMachineDiskOptions().withDeleteOptions(DeleteOptions.DETACH))
1692+
.withExistingSecondaryNetworkInterface(secondaryNic2)
1693+
.apply();
1694+
1695+
// update all back to DELETE, including the newly added data disk and the secondary nic
1696+
vm.update()
1697+
.withPrimaryNetworkInterfaceDeleteOptions(DeleteOptions.DELETE)
1698+
.withDataDisksDeleteOptions(DeleteOptions.DELETE, new ArrayList<>(vm.dataDisks().keySet()).toArray(new Integer[0]))
1699+
.withNetworkInterfacesDeleteOptions(
1700+
DeleteOptions.DELETE,
1701+
vm.networkInterfaceIds().stream().filter(nic -> !nic.equals(vm.primaryNetworkInterfaceId())).toArray(String[]::new))
1702+
.apply();
1703+
1704+
Assertions.assertEquals(DeleteOptions.DELETE, vm.primaryNetworkInterfaceDeleteOptions());
1705+
Assertions.assertTrue(vm.networkInterfaceIds().stream().allMatch(nicId -> DeleteOptions.DELETE.equals(vm.networkInterfaceDeleteOptions(nicId))));
1706+
Assertions.assertTrue(vm.dataDisks().values().stream().allMatch(disk -> DeleteOptions.DELETE.equals(disk.deleteOptions())));
1707+
}
1708+
16111709
// *********************************** helper methods ***********************************
16121710

16131711
private CreatablesInfo prepareCreatableVirtualMachines(

0 commit comments

Comments
 (0)