Skip to content

Commit 99130c4

Browse files
authored
vm-repair: improve repair vm creation and encryption unlock [11/11 Hackathon work] (Azure#2659)
* Remove ADE extension for encrypted VM scenario Attach data disk while vm creation Fix availability zone bug * Fix styling * Suppress linux mount errors
1 parent eb59196 commit 99130c4

File tree

5 files changed

+321
-204
lines changed

5 files changed

+321
-204
lines changed

src/vm-repair/azext_vm_repair/custom.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def create(cmd, vm_name, resource_group_name, repair_password=None, repair_usern
4040

4141
# Init command helper object
4242
command = command_helper(logger, cmd, 'vm repair create')
43-
4443
# Main command calling block
4544
try:
4645
# Fetch source VM data
@@ -69,6 +68,11 @@ def create(cmd, vm_name, resource_group_name, repair_password=None, repair_usern
6968
raise SkuNotAvailableError('Failed to find compatible VM size for source VM\'s OS disk within given region and subscription.')
7069
create_repair_vm_command += ' --size {sku}'.format(sku=sku)
7170

71+
# Set availability zone for vm
72+
if source_vm.zones:
73+
zone = source_vm.zones[0]
74+
create_repair_vm_command += ' --zone {zone}'.format(zone=zone)
75+
7276
# Create new resource group
7377
create_resource_group_command = 'az group create -l {loc} -n {group_name}' \
7478
.format(loc=source_vm.location, group_name=repair_group_name)
@@ -86,25 +90,29 @@ def create(cmd, vm_name, resource_group_name, repair_password=None, repair_usern
8690
# Only add hyperV variable when available
8791
if hyperV_generation:
8892
copy_disk_command += ' --hyper-v-generation {hyperV}'.format(hyperV=hyperV_generation)
93+
# Set availability zone for vm when available
94+
if source_vm.zones:
95+
zone = source_vm.zones[0]
96+
copy_disk_command += ' --zone {zone}'.format(zone=zone)
97+
# Copy OS Disk
98+
logger.info('Copying OS disk of source VM...')
99+
copy_disk_id = _call_az_command(copy_disk_command).strip('\n')
100+
# Add copied OS Disk to VM creat command so that the VM is created with the disk attached
101+
create_repair_vm_command += ' --attach-data-disks {id}'.format(id=copy_disk_id)
89102
# Validate create vm create command to validate parameters before runnning copy disk command
90103
validate_create_vm_command = create_repair_vm_command + ' --validate'
91-
92104
logger.info('Validating VM template before continuing...')
93105
_call_az_command(validate_create_vm_command, secure_params=[repair_password, repair_username])
94-
logger.info('Copying OS disk of source VM...')
95-
copy_disk_id = _call_az_command(copy_disk_command).strip('\n')
96-
97-
attach_disk_command = 'az vm disk attach -g {g} --vm-name {repair} --name {id}' \
98-
.format(g=repair_group_name, repair=repair_vm_name, id=copy_disk_id)
99-
106+
# Create repair VM
100107
logger.info('Creating repair VM...')
101108
_call_az_command(create_repair_vm_command, secure_params=[repair_password, repair_username])
102-
logger.info('Attaching copied disk to repair VM...')
103-
_call_az_command(attach_disk_command)
104109

105110
# Handle encrypted VM cases
106111
if unlock_encrypted_vm:
107-
_unlock_singlepass_encrypted_disk(source_vm, resource_group_name, repair_vm_name, repair_group_name, copy_disk_name, is_linux)
112+
stdout, stderr = _unlock_singlepass_encrypted_disk(repair_vm_name, repair_group_name, is_linux)
113+
logger.debug('Unlock script STDOUT:\n%s', stdout)
114+
if stderr:
115+
logger.warning('Encryption unlock script error was generated:\n%s', stderr)
108116

109117
# UNMANAGED DISK
110118
else:

src/vm-repair/azext_vm_repair/repair_utils.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,18 @@ def _secret_tag_check(resource_group_name, copy_disk_name, secreturl):
271271
_call_az_command(set_tag_command)
272272

273273

274-
def _unlock_singlepass_encrypted_disk(source_vm, resource_group_name, repair_vm_name, repair_group_name, copy_disk_name, is_linux):
274+
def _unlock_singlepass_encrypted_disk(repair_vm_name, repair_group_name, is_linux):
275+
logger.info('Unlocking attached copied disk...')
276+
if is_linux:
277+
return _unlock_mount_linux_encrypted_disk(repair_vm_name, repair_group_name)
278+
return _unlock_mount_windows_encrypted_disk(repair_vm_name, repair_group_name)
279+
280+
281+
def _unlock_singlepass_encrypted_disk_fallback(source_vm, resource_group_name, repair_vm_name, repair_group_name, copy_disk_name, is_linux):
282+
"""
283+
Fallback for unlocking disk when script fails. This will install the ADE extension to unlock the Data disk.
284+
"""
285+
275286
# Installs the extension on repair VM and mounts the disk after unlocking.
276287
encryption_type, key_vault, kekurl, secreturl = _fetch_encryption_settings(source_vm)
277288
if is_linux:
@@ -296,25 +307,31 @@ def _unlock_singlepass_encrypted_disk(source_vm, resource_group_name, repair_vm_
296307
# Validating secret tag and setting original tag if it got changed
297308
_secret_tag_check(resource_group_name, copy_disk_name, secreturl)
298309
logger.debug("Manually unlocking and mounting disk for Linux VMs.")
299-
_manually_unlock_mount_encrypted_disk(repair_vm_name, repair_group_name)
310+
_unlock_mount_linux_encrypted_disk(repair_vm_name, repair_group_name)
300311
except AzCommandError as azCommandError:
301312
error_message = str(azCommandError)
302313
# Linux VM encryption extension bug where it fails and then continue to mount disk manually
303314
if is_linux and "Failed to encrypt data volumes with error" in error_message:
304315
logger.debug("Expected bug for linux VMs. Ignoring error.")
305316
# Validating secret tag and setting original tag if it got changed
306317
_secret_tag_check(resource_group_name, copy_disk_name, secreturl)
307-
_manually_unlock_mount_encrypted_disk(repair_vm_name, repair_group_name)
318+
_unlock_mount_linux_encrypted_disk(repair_vm_name, repair_group_name)
308319
else:
309320
raise
310321

311322

312-
def _manually_unlock_mount_encrypted_disk(repair_vm_name, repair_group_name):
323+
def _unlock_mount_linux_encrypted_disk(repair_vm_name, repair_group_name):
313324
# Unlocks the disk using the phasephrase and mounts it on the repair VM.
314-
LINUX_RUN_SCRIPT_NAME = 'mount-encrypted-disk.sh'
325+
LINUX_RUN_SCRIPT_NAME = 'linux-mount-encrypted-disk.sh'
315326
return _invoke_run_command(LINUX_RUN_SCRIPT_NAME, repair_vm_name, repair_group_name, True)
316327

317328

329+
def _unlock_mount_windows_encrypted_disk(repair_vm_name, repair_group_name):
330+
# Unlocks the disk using the phasephrase and mounts it on the repair VM.
331+
WINDOWS_RUN_SCRIPT_NAME = 'win-mount-encrypted-disk.ps1'
332+
return _invoke_run_command(WINDOWS_RUN_SCRIPT_NAME, repair_vm_name, repair_group_name, False)
333+
334+
318335
def _fetch_compatible_windows_os_urn(source_vm):
319336
location = source_vm.location
320337
fetch_urn_command = 'az vm image list -s "2016-Datacenter" -f WindowsServer -p MicrosoftWindowsServer -l {loc} --verbose --all --query "[?sku==\'2016-Datacenter\'].urn | reverse(sort(@))" -o json'.format(loc=location)

0 commit comments

Comments
 (0)