Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mysql] az mysql flexible-server create/restore/replica create/geo restore: Add --storage-redundancy parameter to support HA storage with zone redundancy #30423

Merged
merged 12 commits into from
Dec 12, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ def cf_mysql_flexible_log(cli_ctx, _):
return get_mysql_flexible_management_client(cli_ctx).log_files


def cf_mysql_flexible_backup(cli_ctx, _):
return get_mysql_flexible_management_client(cli_ctx).long_running_backup


def cf_mysql_flexible_backups(cli_ctx, _):
return get_mysql_flexible_management_client(cli_ctx).backups
return get_mysql_flexible_management_client(cli_ctx).long_running_backups


def cf_mysql_flexible_export(cli_ctx, _):
Expand Down
10 changes: 10 additions & 0 deletions src/azure-cli/azure/cli/command_modules/mysql/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many-
help='Enable or disable accelerated logs. Only support for Business Critical tier. Default value is Enabled.'
)

storage_redundancy_arg_type = CLIArgumentType(
arg_type=get_enum_type(['LocalRedundancy', 'ZoneRedundancy']),
options_list=['--storage-redundancy'],
help='Enable local redundancy or zone redundancy. Zone redundancy only supports Business Critical tier.'
)

maintenance_policy_patch_strategy_arg_type = CLIArgumentType(
arg_type=get_enum_type(['Regular', 'VirtualCanary']),
options_list=['--maintenance-policy-patch-strategy', '--patch-strategy'],
Expand Down Expand Up @@ -347,6 +353,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many-
c.argument('public_access', arg_type=public_access_create_arg_type)
c.argument('vnet', arg_type=vnet_arg_type)
c.argument('vnet_address_prefix', arg_type=vnet_address_prefix_arg_type)
c.argument('storage_redundancy', arg_type=storage_redundancy_arg_type)
c.argument('subnet', arg_type=subnet_arg_type)
c.argument('subnet_address_prefix', arg_type=subnet_address_prefix_arg_type)
c.argument('private_dns_zone_arguments', private_dns_zone_arguments_arg_type)
Expand Down Expand Up @@ -405,6 +412,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many-
c.argument('vnet_address_prefix', arg_type=vnet_address_prefix_arg_type)
c.argument('subnet', arg_type=subnet_arg_type)
c.argument('subnet_address_prefix', arg_type=subnet_address_prefix_arg_type)
c.argument('storage_redundancy', arg_type=storage_redundancy_arg_type)
c.argument('private_dns_zone_arguments', private_dns_zone_arguments_arg_type)
c.argument('zone', arg_type=zone_arg_type)
c.argument('tags', tags_type)
Expand Down Expand Up @@ -436,6 +444,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many-
c.argument('storage_gb', arg_type=storage_gb_arg_type)
c.argument('auto_grow', arg_type=auto_grow_arg_type)
c.argument('accelerated_logs', arg_type=accelerated_logs_arg_type)
c.argument('storage_redundancy', arg_type=storage_redundancy_arg_type)
c.argument('backup_retention', arg_type=mysql_backup_retention_arg_type)
c.argument('geo_redundant_backup', arg_type=geo_redundant_backup_arg_type)
c.argument('public_access', options_list=['--public-access'], arg_type=get_enum_type(['Enabled', 'Disabled']), help='Determines the public access. ')
Expand Down Expand Up @@ -564,6 +573,7 @@ def load_arguments(self, _): # pylint: disable=too-many-statements, too-many-
c.argument('sku_name', arg_type=sku_name_arg_type)
c.argument('storage_gb', arg_type=storage_gb_arg_type)
c.argument('iops', arg_type=iops_arg_type)
c.argument('storage_redundancy', arg_type=storage_redundancy_arg_type)
c.argument('database_port', arg_type=database_port_arg_type)
c.argument('backup_retention', arg_type=mysql_backup_retention_arg_type)
c.argument('geo_redundant_backup', arg_type=geo_redundant_backup_arg_type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def mysql_arguments_validator(db_context, location, tier, sku_name, storage_gb,
public_access=None, version=None, auto_grow=None, replication_role=None, subnet=None,
byok_identity=None, backup_byok_identity=None, byok_key=None, geo_redundant_backup=None,
disable_data_encryption=None, iops=None, auto_io_scaling=None, accelerated_logs=None,
instance=None, data_source_type=None, mode=None,
storage_redundancy=None, instance=None, data_source_type=None, mode=None,
data_source_backup_dir=None, data_source_sas_token=None):
validate_server_name(db_context, server_name, 'Microsoft.DBforMySQL/flexibleServers')

Expand All @@ -134,6 +134,7 @@ def mysql_arguments_validator(db_context, location, tier, sku_name, storage_gb,
disable_data_encryption, geo_redundant_backup, instance)
_mysql_iops_validator(iops, auto_io_scaling, instance)
mysql_accelerated_logs_validator(accelerated_logs, tier)
storage_redundancy_validator(storage_redundancy, tier)
_mysql_import_data_source_type_validator(data_source_type, data_source_backup_dir, data_source_sas_token)
_mysql_import_mode_validator(mode)

Expand Down Expand Up @@ -316,6 +317,12 @@ def mysql_accelerated_logs_validator(accelerated_logs, tier):
"So the accelerated logs will be disabled.")


def storage_redundancy_validator(storage_redundancy, tier):
if tier != "MemoryOptimized" and storage_redundancy is not None and storage_redundancy.lower() == "zoneredundancy":
logger.warning("Zone Redundancy is only supported for Memory Optimized tier. "
"So Local Redundancy will be enabled for your server.")


def _network_arg_validator(subnet, public_access):
if subnet is not None and public_access is not None:
raise CLIError("Incorrect usage : A combination of the parameters --subnet "
Expand Down
19 changes: 14 additions & 5 deletions src/azure-cli/azure/cli/command_modules/mysql/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
cf_mysql_flexible_replica,
cf_mysql_flexible_location_capabilities,
cf_mysql_flexible_log,
cf_mysql_flexible_backup,
cf_mysql_flexible_backups,
cf_mysql_flexible_adadmin,
cf_mysql_flexible_export,
Expand Down Expand Up @@ -69,8 +70,13 @@ def load_command_table(self, _):
client_factory=cf_mysql_flexible_log
)

mysql_flexible_backups_sdk = CliCommandType(
operations_tmpl='azure.mgmt.mysqlflexibleservers.operations#BackupsOperations.{}',
mysql_flexible_long_running_backup_sdk = CliCommandType(
operations_tmpl='azure.mgmt.mysqlflexibleservers.operations#LongRunningBackupOperations.{}',
client_factory=cf_mysql_flexible_backup
)

mysql_flexible_long_running_backups_sdk = CliCommandType(
operations_tmpl='azure.mgmt.mysqlflexibleservers.operations#LongRunningBackupsOperations.{}',
client_factory=cf_mysql_flexible_backups
)

Expand Down Expand Up @@ -185,10 +191,13 @@ def load_command_table(self, _):
g.custom_command('list', 'flexible_server_log_list')
g.custom_command('download', 'flexible_server_log_download')

with self.command_group('mysql flexible-server backup', mysql_flexible_backups_sdk,
with self.command_group('mysql flexible-server backup', mysql_flexible_long_running_backup_sdk,
client_factory=cf_mysql_flexible_backup) as g:
g.command('create', 'begin_create')

with self.command_group('mysql flexible-server backup', mysql_flexible_long_running_backups_sdk,
client_factory=cf_mysql_flexible_backups) as g:
g.command('create', 'put', transform=transform_backup)
g.command('list', 'list_by_server', transform=transform_backups_list)
g.command('list', 'list', transform=transform_backups_list)
g.show_command('show', 'get', transform=transform_backup)

with self.command_group('mysql flexible-server export', mysql_flexible_export_sdk,
Expand Down
52 changes: 42 additions & 10 deletions src/azure-cli/azure/cli/command_modules/mysql/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from ._validators import mysql_arguments_validator, mysql_auto_grow_validator, mysql_georedundant_backup_validator, mysql_restore_tier_validator, mysql_accelerated_logs_validator, \
mysql_retention_validator, mysql_sku_name_validator, mysql_storage_validator, validate_mysql_replica, validate_server_name, \
validate_mysql_tier_update, validate_and_format_restore_point_in_time, validate_public_access_server, mysql_import_single_server_ready_validator, \
mysql_import_version_validator, mysql_import_storage_validator, validate_and_format_maintenance_start_time
mysql_import_version_validator, mysql_import_storage_validator, validate_and_format_maintenance_start_time, storage_redundancy_validator

logger = get_logger(__name__)
DELEGATION_SERVICE_NAME = "Microsoft.DBforMySQL/flexibleServers"
Expand Down Expand Up @@ -337,8 +337,8 @@ def flexible_server_create(cmd, client,
subnet=None, subnet_address_prefix=None, vnet=None, vnet_address_prefix=None,
private_dns_zone_arguments=None, public_access=None,
high_availability=None, zone=None, standby_availability_zone=None,
iops=None, auto_grow=None, auto_scale_iops=None, accelerated_logs=None, geo_redundant_backup=None,
byok_identity=None, backup_byok_identity=None, byok_key=None, backup_byok_key=None,
iops=None, auto_grow=None, auto_scale_iops=None, accelerated_logs=None, storage_redundancy=None,
geo_redundant_backup=None, byok_identity=None, backup_byok_identity=None, byok_key=None, backup_byok_key=None,
maintenance_policy_patch_strategy=None, yes=False):
# Generate missing parameters
location, resource_group_name, server_name = generate_missing_parameters(cmd, location, resource_group_name, server_name)
Expand Down Expand Up @@ -376,6 +376,7 @@ def flexible_server_create(cmd, client,
backup_byok_key=backup_byok_key,
auto_io_scaling=auto_scale_iops,
accelerated_logs=accelerated_logs,
storage_redundancy=storage_redundancy,
iops=iops)
list_skus_info = get_mysql_list_skus_info(db_context.cmd, location)
iops_info = list_skus_info['iops_info']
Expand Down Expand Up @@ -404,11 +405,14 @@ def flexible_server_create(cmd, client,

accelerated_logs = _determine_acceleratedLogs(accelerated_logs, tier)

storage_redundancy = _determine_storage_redundancy(storage_redundancy, tier)

storage = models.Storage(storage_size_gb=storage_gb,
iops=iops,
auto_grow=auto_grow,
auto_io_scaling=auto_scale_iops,
log_on_disk=accelerated_logs)
log_on_disk=accelerated_logs,
storage_redundancy=storage_redundancy)

backup = models.Backup(backup_retention_days=backup_retention, geo_redundant_backup=geo_redundant_backup)

Expand Down Expand Up @@ -703,7 +707,8 @@ def flexible_server_import_replica_stop(client, resource_group_name, server_name
def flexible_server_restore(cmd, client, resource_group_name, server_name, source_server, restore_point_in_time=None, zone=None,
no_wait=False, subnet=None, subnet_address_prefix=None, vnet=None, vnet_address_prefix=None,
private_dns_zone_arguments=None, public_access=None, yes=False, sku_name=None, tier=None, database_port=None,
storage_gb=None, auto_grow=None, accelerated_logs=None, backup_retention=None, geo_redundant_backup=None, tags=None):
storage_gb=None, auto_grow=None, accelerated_logs=None, storage_redundancy=None, backup_retention=None,
geo_redundant_backup=None, tags=None):
provider = 'Microsoft.DBforMySQL'
server_name = server_name.lower()

Expand Down Expand Up @@ -756,6 +761,11 @@ def flexible_server_restore(cmd, client, resource_group_name, server_name, sourc
else:
mysql_accelerated_logs_validator(accelerated_logs, tier)

if not storage_redundancy:
storage_redundancy = source_server_object.storage.storage_redundancy
else:
storage_redundancy_validator(storage_redundancy, tier)

if not backup_retention:
backup_retention = source_server_object.backup.backup_retention_days
else:
Expand All @@ -779,7 +789,7 @@ def flexible_server_restore(cmd, client, resource_group_name, server_name, sourc

storage = models.Storage(storage_size_gb=storage_gb, iops=iops, auto_grow=auto_grow,
auto_io_scaling=source_server_object.storage.auto_io_scaling,
log_on_disk=accelerated_logs)
log_on_disk=accelerated_logs, storage_redundancy=storage_redundancy)

backup = models.Backup(backup_retention_days=backup_retention, geo_redundant_backup=geo_redundant_backup)

Expand Down Expand Up @@ -842,7 +852,8 @@ def flexible_server_restore(cmd, client, resource_group_name, server_name, sourc
def flexible_server_georestore(cmd, client, resource_group_name, server_name, source_server, location, zone=None, no_wait=False,
subnet=None, subnet_address_prefix=None, vnet=None, vnet_address_prefix=None, tags=None,
private_dns_zone_arguments=None, public_access=None, yes=False, sku_name=None, tier=None,
storage_gb=None, auto_grow=None, accelerated_logs=None, backup_retention=None, geo_redundant_backup=None):
storage_gb=None, auto_grow=None, accelerated_logs=None, storage_redundancy=None,
backup_retention=None, geo_redundant_backup=None):
provider = 'Microsoft.DBforMySQL'
server_name = server_name.lower()

Expand Down Expand Up @@ -889,6 +900,11 @@ def flexible_server_georestore(cmd, client, resource_group_name, server_name, so
else:
mysql_accelerated_logs_validator(accelerated_logs, tier)

if not storage_redundancy:
storage_redundancy = source_server_object.storage.storage_redundancy
else:
storage_redundancy_validator(storage_redundancy, tier)

if not backup_retention:
backup_retention = source_server_object.backup.backup_retention_days
else:
Expand All @@ -915,7 +931,7 @@ def flexible_server_georestore(cmd, client, resource_group_name, server_name, so

storage = models.Storage(storage_size_gb=storage_gb, iops=iops, auto_grow=auto_grow,
auto_io_scaling=source_server_object.storage.auto_io_scaling,
log_on_disk=accelerated_logs)
log_on_disk=accelerated_logs, storage_redundancy=storage_redundancy)

backup = models.Backup(backup_retention_days=backup_retention, geo_redundant_backup=geo_redundant_backup)

Expand Down Expand Up @@ -1311,7 +1327,8 @@ def flexible_parameter_update_batch(client, server_name, resource_group_name, so
# Custom functions for server replica, will add MySQL part after backend ready in future
def flexible_replica_create(cmd, client, resource_group_name, source_server, replica_name, location=None, tags=None, sku_name=None,
private_dns_zone_arguments=None, vnet=None, subnet=None, zone=None, public_access=None, no_wait=False,
storage_gb=None, iops=None, geo_redundant_backup=None, backup_retention=None, tier=None, database_port=None):
storage_gb=None, iops=None, storage_redundancy=None, geo_redundant_backup=None, backup_retention=None,
tier=None, database_port=None):
provider = 'Microsoft.DBforMySQL'
replica_name = replica_name.lower()

Expand Down Expand Up @@ -1356,12 +1373,18 @@ def flexible_replica_create(cmd, client, resource_group_name, source_server, rep
if not iops:
iops = source_server_object.storage.iops

if not storage_redundancy:
storage_redundancy = source_server_object.storage.storage_redundancy
else:
storage_redundancy_validator(storage_redundancy, tier)

identity, data_encryption = get_identity_and_data_encryption(source_server_object)

storage = models.Storage(storage_size_gb=storage_gb,
iops=iops,
auto_grow="Enabled",
auto_io_scaling=source_server_object.storage.auto_io_scaling)
auto_io_scaling=source_server_object.storage.auto_io_scaling,
storage_redundancy=storage_redundancy)

backup = models.Backup(backup_retention_days=backup_retention, geo_redundant_backup=geo_redundant_backup)

Expand Down Expand Up @@ -1649,6 +1672,15 @@ def _determine_acceleratedLogs(accelerated_logs, tier):
return accelerated_logs


def _determine_storage_redundancy(storage_redundancy, tier):
if storage_redundancy is None:
if tier == "MemoryOptimized":
storage_redundancy = "ZoneRedundancy"
else:
storage_redundancy = "LocalRedundancy"
return storage_redundancy


def get_free_iops(storage_in_mb, iops_info, tier, sku_name):
free_iops = MINIMUM_IOPS + (storage_in_mb // 1024) * 3
max_supported_iops = iops_info[tier][sku_name] # free iops cannot exceed maximum supported iops for the sku
Expand Down
Loading
Loading