Skip to content

Commit

Permalink
[Compute] az vm disk detach: Add parameter --force-detach to supp…
Browse files Browse the repository at this point in the history
…ort force-detaching managed data disks from a VM (#23346)
  • Loading branch information
yanzhudd authored Jul 28, 2022
1 parent 2ad25b0 commit 8916d48
Show file tree
Hide file tree
Showing 10 changed files with 3,540 additions and 12 deletions.
3 changes: 3 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1821,6 +1821,9 @@
- name: Detach a data disk from a VM.
text: >
az vm disk detach -g MyResourceGroup --vm-name MyVm --name disk_name
- name: Force detach a data disk from a VM.
text: >
az vm disk detach -g MyResourceGroup --vm-name MyVm --name disk_name --force-detach
"""

helps['vm encryption'] = """
Expand Down
1 change: 1 addition & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ def load_arguments(self, _):

with self.argument_context('vm disk detach') as c:
c.argument('disk_name', arg_type=name_arg_type, help='The data disk name.')
c.argument('force_detach', action='store_true', min_api='2020-12-01', help='Force detach managed data disks from a VM.')

with self.argument_context('vm encryption enable') as c:
c.argument('encrypt_format_all', action='store_true', help='Encrypts-formats data disks instead of encrypting them. Encrypt-formatting is a lot faster than in-place encryption but wipes out the partition getting encrypt-formatted. (Only supported for Linux virtual machines.)')
Expand Down
4 changes: 2 additions & 2 deletions src/azure-cli/azure/cli/command_modules/vm/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ def load_command_table(self, _):

with self.command_group('vm disk', compute_vm_sdk, min_api='2017-03-30') as g:
g.custom_command('attach', 'attach_managed_data_disk', validator=process_vm_disk_attach_namespace)
g.custom_command('detach', 'detach_data_disk')
g.custom_command('detach', 'detach_managed_data_disk')

with self.command_group('vm encryption', custom_command_type=compute_disk_encryption_custom) as g:
g.custom_command('enable', 'encrypt_vm', validator=process_disk_encryption_namespace)
Expand Down Expand Up @@ -446,7 +446,7 @@ def load_command_table(self, _):

with self.command_group('vm unmanaged-disk', compute_vm_sdk) as g:
g.custom_command('attach', 'attach_unmanaged_data_disk')
g.custom_command('detach', 'detach_data_disk')
g.custom_command('detach', 'detach_unmanaged_data_disk')
g.custom_command('list', 'list_unmanaged_disks')

with self.command_group('vm user', compute_vm_sdk, supports_no_wait=True) as g:
Expand Down
30 changes: 28 additions & 2 deletions src/azure-cli/azure/cli/command_modules/vm/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1916,8 +1916,8 @@ def attach_managed_data_disk(cmd, resource_group_name, vm_name, disk=None, ids=N
set_vm(cmd, vm)


def detach_data_disk(cmd, resource_group_name, vm_name, disk_name):
# here we handle both unmanaged or managed disk
def detach_unmanaged_data_disk(cmd, resource_group_name, vm_name, disk_name):
# here we handle unmanaged disk
vm = get_vm_to_update(cmd, resource_group_name, vm_name)
# pylint: disable=no-member
leftovers = [d for d in vm.storage_profile.data_disks if d.name.lower() != disk_name.lower()]
Expand All @@ -1928,6 +1928,32 @@ def detach_data_disk(cmd, resource_group_name, vm_name, disk_name):
# endregion


def detach_managed_data_disk(cmd, resource_group_name, vm_name, disk_name, force_detach=None):
# here we handle managed disk
vm = get_vm_to_update(cmd, resource_group_name, vm_name)
if not force_detach:
# pylint: disable=no-member
leftovers = [d for d in vm.storage_profile.data_disks if d.name.lower() != disk_name.lower()]
if len(vm.storage_profile.data_disks) == len(leftovers):
raise ResourceNotFoundError("No disk with the name '{}' was found".format(disk_name))
else:
DiskDetachOptionTypes = cmd.get_models('DiskDetachOptionTypes', resource_type=ResourceType.MGMT_COMPUTE,
operation_group='virtual_machines')
leftovers = vm.storage_profile.data_disks
is_contains = False
for d in leftovers:
if d.name.lower() == disk_name.lower():
d.to_be_detached = True
d.detach_option = DiskDetachOptionTypes.FORCE_DETACH
is_contains = True
break
if not is_contains:
raise ResourceNotFoundError("No disk with the name '{}' was found".format(disk_name))
vm.storage_profile.data_disks = leftovers
set_vm(cmd, vm)
# endregion


# region VirtualMachines Extensions
def list_extensions(cmd, resource_group_name, vm_name):
vm = get_vm(cmd, resource_group_name, vm_name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
_get_extension_instance_name,
get_boot_log)
from azure.cli.command_modules.vm.custom import \
(attach_unmanaged_data_disk, detach_data_disk, get_vmss_instance_view)
(attach_unmanaged_data_disk, detach_unmanaged_data_disk, get_vmss_instance_view)

from azure.cli.core import AzCommandsLoader
from azure.cli.core.commands import AzCliCommand
Expand Down Expand Up @@ -206,7 +206,7 @@ def test_deattach_disk_on_vm(self, mock_vm_set, mock_vm_get_to_update):
mock_vm_get_to_update.return_value = vm

# execute
detach_data_disk(cmd, 'rg1', 'vm1', 'd1')
detach_unmanaged_data_disk(cmd, 'rg1', 'vm1', 'd1')

# assert
self.assertTrue(mock_vm_get_to_update.called)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
_get_extension_instance_name,
get_boot_log)
from azure.cli.command_modules.vm.custom import \
(attach_unmanaged_data_disk, detach_data_disk, get_vmss_instance_view)
(attach_unmanaged_data_disk, detach_unmanaged_data_disk, get_vmss_instance_view)

from azure.cli.core import AzCommandsLoader
from azure.cli.core.commands import AzCliCommand
Expand Down Expand Up @@ -206,7 +206,7 @@ def test_deattach_disk_on_vm(self, mock_vm_set, mock_vm_get_to_update):
mock_vm_get_to_update.return_value = vm

# execute
detach_data_disk(cmd, 'rg1', 'vm1', 'd1')
detach_unmanaged_data_disk(cmd, 'rg1', 'vm1', 'd1')

# assert
self.assertTrue(mock_vm_get_to_update.called)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
_get_extension_instance_name,
get_boot_log)
from azure.cli.command_modules.vm.custom import \
(attach_unmanaged_data_disk, detach_data_disk, get_vmss_instance_view)
(attach_unmanaged_data_disk, detach_unmanaged_data_disk, get_vmss_instance_view)

from azure.cli.core import AzCommandsLoader
from azure.cli.core.commands import AzCliCommand
Expand Down Expand Up @@ -218,7 +218,7 @@ def test_deattach_disk_on_vm(self, mock_vm_set, mock_vm_get_to_update):
mock_vm_get_to_update.return_value = vm

# execute
detach_data_disk(cmd, 'rg1', 'vm1', 'd1')
detach_unmanaged_data_disk(cmd, 'rg1', 'vm1', 'd1')

# assert
self.assertTrue(mock_vm_get_to_update.called)
Expand Down
Loading

0 comments on commit 8916d48

Please sign in to comment.