Skip to content

Commit

Permalink
[RecoveryServices Backup]Added disk exclusion Feature for IAASVM (#11717
Browse files Browse the repository at this point in the history
)

* Added disk exclusion tests

* resolving comments

* updated history.rst

* removed redundant parameter
  • Loading branch information
sambitratha authored and qwordy committed Jan 2, 2020
1 parent fc532b4 commit 1c88592
Show file tree
Hide file tree
Showing 8 changed files with 18,505 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/azure-cli/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Release History

* Added new command 'backup protection undelete' to enable soft-delete feature for IaasVM workload
* Added new parameter '--soft-delete-feature-state' to set backup-properties command
* Added disk exclusion support for IaasVM workload

**Compute**

Expand Down
8 changes: 8 additions & 0 deletions src/azure-cli/azure/cli/command_modules/backup/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,14 @@
text: az backup protection resume --vault-name MyVault --resource-group MyResourceGroup --container-name MyContainer --item-name MyItem --policy-name MyPolicy
"""

helps['backup protection update-for-vm'] = """
type: command
short-summary: Update disk exclusion settings associated with a backed up VM item.
examples:
- name: Update disk exclusion settings associated with a backed up VM item.
text: az backup protection update-for-vm --vault-name MyVault --resource-group MyResourceGroup --container-name MyContainer --item-name MyItem --disk-list-setting exclude --diskslist 1
"""

helps['backup recoveryconfig'] = """
type: group
short-summary: Manage recovery configuration of an Azure workload backed up item.
Expand Down
15 changes: 14 additions & 1 deletion src/azure-cli/azure/cli/command_modules/backup/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
protectable_item_name_type_help = """Specify the resource name to be protected by Azure Backup service."""
backup_type_help = """'Full, Differential, Log, Copy-only-full' for backup Item type 'MSSQL'. 'Full, Differential' for backup item type 'SAPHANA'."""
retain_until_help = """The date until which this backed up copy will be available for retrieval, in UTC (d-m-Y). For SAPHANA and SQL workload, retain-until parameter value will be overridden by the underlying policy."""
diskslist_help = """List of disks to be excluded or included."""
disk_list_setting_help = """option to decide whether to include or exclude the disk or reset any previous settings to default behavior"""

vault_name_type = CLIArgumentType(help='Name of the Recovery services vault.', options_list=['--vault-name', '-v'], completer=get_resource_name_completion_list('Microsoft.RecoveryServices/vaults'))
container_name_type = CLIArgumentType(help=container_name_help, options_list=['--container-name', '-c'])
Expand All @@ -53,6 +55,7 @@
protectable_item_type = CLIArgumentType(help=workload_type_help, options_list=['--protectable-item-type'], arg_type=get_enum_type(allowed_protectable_item_type))
target_server_type = CLIArgumentType(help=target_server_type_help, options_list=['--target-server-type'], arg_type=get_enum_type(allowed_protectable_item_type))
protectable_item_name_type = CLIArgumentType(help=protectable_item_name_type_help, options_list=['--protectable-item-name'])
diskslist_type = CLIArgumentType(nargs='+', help=diskslist_help)


# pylint: disable=too-many-statements
Expand Down Expand Up @@ -173,7 +176,7 @@ def load_arguments(self, _):
c.argument('policy_name', policy_name_type)

# TODO: Need to use item.id once https://github.com/Azure/msrestazure-for-python/issues/80 is fixed.
for command in ['backup-now', 'disable', 'auto-disable-for-azurewl', 'resume', 'undelete']:
for command in ['backup-now', 'disable', 'auto-disable-for-azurewl', 'resume', 'undelete', 'update-for-vm']:
with self.argument_context('backup protection ' + command) as c:
c.argument('container_name', container_name_type)
c.argument('item_name', item_name_type)
Expand All @@ -193,6 +196,14 @@ def load_arguments(self, _):
with self.argument_context('backup protection check-vm') as c:
c.argument('vm_id', help='ID of the virtual machine to be checked for protection.')

with self.argument_context('backup protection enable-for-vm') as c:
c.argument('diskslist', diskslist_type)
c.argument('disk_list_setting', arg_type=get_enum_type(['include', 'exclude']), options_list=['--disk-list-setting'], help=disk_list_setting_help)

with self.argument_context('backup protection update-for-vm') as c:
c.argument('diskslist', diskslist_type)
c.argument('disk_list_setting', arg_type=get_enum_type(['include', 'exclude', 'resetexclusionsettings']), options_list=['--disk-list-setting'], help=disk_list_setting_help)

with self.argument_context('backup protection enable-for-azurefileshare') as c:
c.argument('azure_file_share', options_list=['--azure-file-share'], help='Name of the Azure FileShare.')
c.argument('storage_account', options_list=['--storage-account'], help='Name of the Storage Account of the FileShare.')
Expand Down Expand Up @@ -227,6 +238,8 @@ def load_arguments(self, _):
c.argument('storage_account', help='Name or ID of the staging storage account. The VM configuration will be restored to this storage account. See the help for --restore-to-staging-storage-account parameter for more info.')
c.argument('restore_to_staging_storage_account', arg_type=get_three_state_flag(), help='Use this flag when you want disks to be restored to the staging storage account using the --storage-account parameter. When not specified, disks will be restored to their original storage accounts. Default: false.')
c.argument('target_resource_group', options_list=['--target-resource-group', '-t'], help='Use this to specify the target resource group in which the restored disks will be saved')
c.argument('diskslist', diskslist_type)
c.argument('restore_only_osdisk', arg_type=get_three_state_flag(), help='Use this flag to restore only OS disks of a backed up VM.')

with self.argument_context('backup restore restore-azurefileshare') as c:
c.argument('resolve_conflict', resolve_conflict_type)
Expand Down
1 change: 1 addition & 0 deletions src/azure-cli/azure/cli/command_modules/backup/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def load_command_table(self, _):
with self.command_group('backup protection', backup_custom_base, client_factory=protected_items_cf) as g:
g.command('check-vm', 'check_protection_enabled_for_vm')
g.command('enable-for-vm', 'enable_protection_for_vm')
g.command('update-for-vm', 'update_protection_for_vm')

with self.command_group('backup protection', custom_command_type=backup_custom_base, client_factory=protected_items_cf) as g:
g.custom_command('backup-now', 'backup_now', client_factory=backups_cf)
Expand Down
71 changes: 66 additions & 5 deletions src/azure-cli/azure/cli/command_modules/backup/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import os
from datetime import datetime, timedelta
from six.moves.urllib.parse import urlparse # pylint: disable=import-error

# pylint: disable=too-many-lines
from knack.log import get_logger

from msrest.paging import Paged
Expand All @@ -20,7 +20,7 @@
AzureIaaSClassicComputeVMProtectedItem, ProtectionState, IaasVMBackupRequest, BackupRequestResource, \
IaasVMRestoreRequest, RestoreRequestResource, BackupManagementType, WorkloadType, OperationStatusValues, \
JobStatus, ILRRequestResource, IaasVMILRRegistrationRequest, BackupResourceConfig, BackupResourceConfigResource, \
BackupResourceVaultConfig, BackupResourceVaultConfigResource
BackupResourceVaultConfig, BackupResourceVaultConfigResource, DiskExclusionProperties, ExtendedProperties

from azure.cli.core.util import CLIError, sdk_no_wait
from azure.cli.command_modules.backup._client_factory import (
Expand Down Expand Up @@ -195,7 +195,8 @@ def check_protection_enabled_for_vm(cmd, vm_id):
return None


def enable_protection_for_vm(cmd, client, resource_group_name, vault_name, vm, policy_name):
def enable_protection_for_vm(cmd, client, resource_group_name, vault_name, vm, policy_name, diskslist=None,
disk_list_setting=None):
vm_name, vm_rg = _get_resource_name_and_rg(resource_group_name, vm)
vm = virtual_machines_cf(cmd.cli_ctx).get(vm_rg, vm_name)
vault = vaults_cf(cmd.cli_ctx).get(resource_group_name, vault_name)
Expand Down Expand Up @@ -234,6 +235,49 @@ def enable_protection_for_vm(cmd, client, resource_group_name, vault_name, vm, p
vm_item_properties = _get_vm_item_properties_from_vm_type(vm.type)
vm_item_properties.policy_id = policy.id
vm_item_properties.source_resource_id = protectable_item.properties.virtual_machine_id

if disk_list_setting is not None:
if diskslist is None:
raise CLIError("Please provide LUNs of disks that will be included or excluded.")
is_inclusion_list = False
if disk_list_setting == "include":
is_inclusion_list = True
disk_exclusion_properties = DiskExclusionProperties(disk_lun_list=diskslist,
is_inclusion_list=is_inclusion_list)
extended_properties = ExtendedProperties(disk_exclusion_properties=disk_exclusion_properties)
vm_item_properties.extended_properties = extended_properties

vm_item = ProtectedItemResource(properties=vm_item_properties)

# Trigger enable protection and wait for completion
result = sdk_no_wait(True, client.create_or_update,
vault_name, resource_group_name, fabric_name, container_uri, item_uri, vm_item)
return _track_backup_job(cmd.cli_ctx, result, vault_name, resource_group_name)


def update_protection_for_vm(cmd, client, resource_group_name, vault_name, item, diskslist=None,
disk_list_setting=None):
container_uri = _get_protection_container_uri_from_id(item.id)
item_uri = item.name
vm_type = '/'.join(item.properties.virtual_machine_id.split('/')[-3:-1])
vm_item_properties = _get_vm_item_properties_from_vm_type(vm_type)
vm_item_properties.policy_id = item.properties.policy_id
vm_item_properties.source_resource_id = item.properties.virtual_machine_id

if disk_list_setting is not None:
if disk_list_setting.lower() == "resetexclusionsettings":
disk_exclusion_properties = None
else:
if diskslist is None:
raise CLIError("Please provide LUNs of disks that will be included or excluded.")
is_inclusion_list = False
if disk_list_setting.lower() == "include":
is_inclusion_list = True
disk_exclusion_properties = DiskExclusionProperties(disk_lun_list=diskslist,
is_inclusion_list=is_inclusion_list)
extended_properties = ExtendedProperties(disk_exclusion_properties=disk_exclusion_properties)
vm_item_properties.extended_properties = extended_properties

vm_item = ProtectedItemResource(properties=vm_item_properties)

# Trigger enable protection and wait for completion
Expand Down Expand Up @@ -379,8 +423,10 @@ def _should_use_original_storage_account(recovery_point, restore_to_staging_stor
return use_original_storage_account


# pylint: disable=too-many-locals
def restore_disks(cmd, client, resource_group_name, vault_name, container_name, item_name, rp_name, storage_account,
target_resource_group=None, restore_to_staging_storage_account=None):
target_resource_group=None, restore_to_staging_storage_account=None, restore_only_osdisk=None,
diskslist=None):
item = show_item(cmd, backup_protected_items_cf(cmd.cli_ctx), resource_group_name, vault_name, container_name,
item_name, "AzureIaasVM", "VM")
_validate_item(item)
Expand Down Expand Up @@ -410,14 +456,24 @@ def restore_disks(cmd, client, resource_group_name, vault_name, container_name,
target_rg_id = None
if recovery_point.properties.is_managed_virtual_machine and target_resource_group is not None:
target_rg_id = '/'.join(_source_resource_id.split('/')[:4]) + "/" + target_resource_group

_validate_restore_disk_parameters(restore_only_osdisk, diskslist)
restore_disk_lun_list = None
if restore_only_osdisk:
restore_disk_lun_list = []

if diskslist:
restore_disk_lun_list = diskslist

trigger_restore_properties = IaasVMRestoreRequest(create_new_cloud_service=True,
recovery_point_id=rp_name,
recovery_type='RestoreDisks',
region=vault_location,
storage_account_id=_storage_account_id,
source_resource_id=_source_resource_id,
target_resource_group_id=target_rg_id,
original_storage_account_option=use_original_storage_account)
original_storage_account_option=use_original_storage_account,
restore_disk_lun_list=restore_disk_lun_list)
trigger_restore_request = RestoreRequestResource(properties=trigger_restore_properties)

# Trigger restore
Expand Down Expand Up @@ -756,6 +812,11 @@ def _validate_object(obj, error_message):
raise ValueError(error_message)


def _validate_restore_disk_parameters(restore_only_osdisk, diskslist):
if restore_only_osdisk and diskslist is not None:
logger.warning("Value of diskslist parameter will be ignored as restore-only-osdisk is set to be true.")


# Tracking Utilities
# pylint: disable=inconsistent-return-statements
def _track_backup_ilr(cli_ctx, result, vault_name, resource_group):
Expand Down
25 changes: 21 additions & 4 deletions src/azure-cli/azure/cli/command_modules/backup/custom_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,23 @@ def check_protection_enabled_for_vm(cmd, vm_id):
return custom.check_protection_enabled_for_vm(cmd, vm_id)


def enable_protection_for_vm(cmd, client, resource_group_name, vault_name, vm, policy_name):
return custom.enable_protection_for_vm(cmd, client, resource_group_name, vault_name, vm, policy_name)
def enable_protection_for_vm(cmd, client, resource_group_name, vault_name, vm, policy_name, diskslist=None,
disk_list_setting=None):
return custom.enable_protection_for_vm(cmd, client, resource_group_name, vault_name, vm, policy_name,
diskslist, disk_list_setting)


def update_protection_for_vm(cmd, client, resource_group_name, vault_name, container_name, item_name, diskslist,
disk_list_setting):
items_client = backup_protected_items_cf(cmd.cli_ctx)
item = show_item(cmd, items_client, resource_group_name, vault_name, container_name, item_name,
"AzureIaasVM", "VM")
custom_help.validate_item(item)

if isinstance(item, list):
raise CLIError("Multiple items found. Please give native names instead.")
return custom.update_protection_for_vm(cmd, client, resource_group_name, vault_name, item, diskslist,
disk_list_setting)


def enable_protection_for_azure_wl(cmd, client, resource_group_name, vault_name, policy_name, protectable_item_type,
Expand Down Expand Up @@ -273,9 +288,11 @@ def disable_auto_for_azure_wl(client, resource_group_name, vault_name, item_name


def restore_disks(cmd, client, resource_group_name, vault_name, container_name, item_name, rp_name, storage_account,
target_resource_group=None, restore_to_staging_storage_account=None):
target_resource_group=None, restore_to_staging_storage_account=None, restore_only_osdisk=None,
diskslist=None):
return custom.restore_disks(cmd, client, resource_group_name, vault_name, container_name, item_name, rp_name,
storage_account, target_resource_group, restore_to_staging_storage_account)
storage_account, target_resource_group, restore_to_staging_storage_account,
restore_only_osdisk, diskslist)


def enable_for_azurefileshare(cmd, client, resource_group_name, vault_name, policy_name, storage_account,
Expand Down
Loading

0 comments on commit 1c88592

Please sign in to comment.