Skip to content

Commit

Permalink
[Mysql] `az mysql flexible-server create/restore/replica create/geo r…
Browse files Browse the repository at this point in the history
…estore`: Add `--storage-redundancy` parameter to support HA storage with zone redundancy (#30423)

* complete code

* fix lint

* code complete

* fix linter problems

* fix test

* fix test

* Update custom.py

* update test files
  • Loading branch information
linyudoa authored Dec 12, 2024
1 parent bf7352f commit 0d770d9
Show file tree
Hide file tree
Showing 39 changed files with 49,637 additions and 47,797 deletions.
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
9 changes: 8 additions & 1 deletion src/azure-cli/azure/cli/command_modules/mysql/_validators.py
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

0 comments on commit 0d770d9

Please sign in to comment.