Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

from azure.cli.core.breaking_change import register_argument_deprecate

register_argument_deprecate('postgres flexible-server create', '--high-availability', redirect='--zonal-resiliency')
register_argument_deprecate('postgres flexible-server update', '--high-availability', redirect='--zonal-resiliency')
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@
az postgres flexible-server create --location northeurope --resource-group testGroup \\
--name testserver --admin-user username --admin-password password \\
--sku-name Standard_D2s_v3 --tier GeneralPurpose --public-access 153.24.26.117 --storage-size 128 \\
--tags "key=value" --version 17 --high-availability ZoneRedundant --zone 1 \\
--tags "key=value" --version 17 --zonal-resiliency Enabled --zone 1 \\
--standby-zone 3
- name: >
Create server with high availability feature enabled that allows primary and standby in the same zone when multi-zone capacity is unavailable.
text: >
az postgres flexible-server create -g testGroup -n testCluster --location testLocation --zonal-resiliency Enabled --allow-same-zone
- name: >
Create a PostgreSQL flexible server using Premium SSD v2 Disks.
text: >
Expand Down
16 changes: 16 additions & 0 deletions src/azure-cli/azure/cli/command_modules/rdbms/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,18 @@ def _flexible_server_params(command_group):
help='Enable (ZoneRedundant or SameZone) or disable high availability feature.'
)

zonal_resiliency_arg_type = CLIArgumentType(
arg_type=get_enum_type(['Enabled', 'Disabled']),
options_list=['--zonal-resiliency'],
help='Enable or disable high availability feature.'
)

allow_same_zone_arg_type = CLIArgumentType(
options_list=['--allow-same-zone'],
action='store_true',
help='Allow primary and standby in the same zone when multi-zone capacity is unavailable.'
)

mysql_version_upgrade_arg_type = CLIArgumentType(
arg_type=get_enum_type(['8']),
options_list=['--version', '-v'],
Expand Down Expand Up @@ -607,6 +619,8 @@ def _flexible_server_params(command_group):
c.argument('performance_tier', default=None, arg_type=performance_tier_arg_type)
c.argument('create_cluster', default='Server', arg_type=cluster_option_arg_type)
c.argument('cluster_size', default=None, arg_type=create_node_count_arg_type)
c.argument('zonal_resiliency', arg_type=zonal_resiliency_arg_type, default="Disabled")
c.argument('allow_same_zone', arg_type=allow_same_zone_arg_type, default=False)
elif command_group == 'mysql':
c.argument('tier', default='Burstable', arg_type=tier_arg_type)
c.argument('sku_name', default='Standard_B1ms', arg_type=sku_name_arg_type)
Expand Down Expand Up @@ -749,6 +763,8 @@ def _flexible_server_params(command_group):
c.argument('password_auth', arg_type=password_auth_arg_type)
c.argument('private_dns_zone_arguments', private_dns_zone_arguments_arg_type)
c.argument('cluster_size', default=None, arg_type=update_node_count_arg_type)
c.argument('zonal_resiliency', arg_type=zonal_resiliency_arg_type)
c.argument('allow_same_zone', arg_type=allow_same_zone_arg_type)
c.argument('yes', arg_type=yes_arg_type)

with self.argument_context('{} flexible-server upgrade'.format(command_group)) as c:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ def flexible_server_create(cmd, client,
password_auth=None, administrator_login=None, administrator_login_password=None,
tags=None, 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,
high_availability=None, zonal_resiliency=None, allow_same_zone=False,
zone=None, standby_availability_zone=None,
geo_redundant_backup=None, byok_identity=None, byok_key=None, backup_byok_identity=None, backup_byok_key=None,
auto_grow=None, performance_tier=None,
storage_type=None, iops=None, throughput=None, create_cluster=None, cluster_size=None, yes=False):
Expand All @@ -85,8 +86,10 @@ def flexible_server_create(cmd, client,
logging_name='PostgreSQL', command_group='postgres', server_client=client, location=location)

server_name = server_name.lower()
high_availability_mode = high_availability

if (sku_name is None) or (version is None):
if (sku_name is None) or (version is None) or \
(zonal_resiliency is not None and zonal_resiliency.lower() != 'disabled'):
list_location_capability_info = get_postgres_location_capability_info(cmd, location)

# set sku_name from capability API
Expand All @@ -103,6 +106,10 @@ def flexible_server_create(cmd, client,
if version is None:
supported_server_versions = sorted(list_location_capability_info['supported_server_versions'])
version = supported_server_versions[-1]
# set high availability from capability API
if (zonal_resiliency is not None and zonal_resiliency.lower() != 'disabled'):
single_az = list_location_capability_info['single_az']
high_availability_mode = 'SameZone' if single_az and allow_same_zone else 'ZoneRedundant'

pg_arguments_validator(db_context,
server_name=server_name,
Expand All @@ -113,6 +120,8 @@ def flexible_server_create(cmd, client,
storage_type=storage_type,
iops=iops, throughput=throughput,
high_availability=high_availability,
zonal_resiliency=zonal_resiliency,
allow_same_zone=allow_same_zone,
standby_availability_zone=standby_availability_zone,
zone=zone,
subnet=subnet,
Expand Down Expand Up @@ -155,7 +164,7 @@ def flexible_server_create(cmd, client,

sku = postgresql_flexibleservers.models.Sku(name=sku_name, tier=tier)

high_availability = postgresql_flexibleservers.models.HighAvailability(mode=high_availability,
high_availability = postgresql_flexibleservers.models.HighAvailability(mode=high_availability_mode,
standby_availability_zone=standby_availability_zone)

is_password_auth_enabled = bool(password_auth is not None and password_auth.lower() == 'enabled')
Expand Down Expand Up @@ -319,6 +328,8 @@ def flexible_server_update_custom_func(cmd, client, instance,
backup_retention=None,
administrator_login_password=None,
high_availability=None,
zonal_resiliency=None,
allow_same_zone=False,
standby_availability_zone=None,
maintenance_window=None,
byok_identity=None, byok_key=None,
Expand Down Expand Up @@ -349,6 +360,8 @@ def flexible_server_update_custom_func(cmd, client, instance,
iops=iops,
throughput=throughput,
high_availability=high_availability,
zonal_resiliency=zonal_resiliency,
allow_same_zone=allow_same_zone,
zone=instance.availability_zone,
standby_availability_zone=standby_availability_zone,
byok_identity=byok_identity,
Expand Down Expand Up @@ -464,6 +477,13 @@ def flexible_server_update_custom_func(cmd, client, instance,

# High availability can't be updated with existing properties
high_availability_param = postgresql_flexibleservers.models.HighAvailability()
if zonal_resiliency is not None:
if zonal_resiliency.lower() == 'disabled':
high_availability = 'Disabled'
else:
list_location_capability_info = get_postgres_location_capability_info(cmd, location)
single_az = list_location_capability_info['single_az']
high_availability = 'SameZone' if single_az and allow_same_zone else 'ZoneRedundant'
if high_availability:
high_availability_param.mode = high_availability

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,13 @@ def _test_flexible_server_mgmt(self, database_engine, resource_group):
tier = 'GeneralPurpose'
backup_retention = 7
server_name = self.create_random_name(SERVER_NAME_PREFIX, SERVER_NAME_MAX_LENGTH)
zonal_resiliency_value = 'Enabled'
ha_value = 'ZoneRedundant'

self.cmd('{} flexible-server create -g {} -n {} --backup-retention {} --sku-name {} --tier {} \
--storage-size {} -u {} --version {} --tags keys=3 --high-availability {} \
--storage-size {} -u {} --version {} --tags keys=3 --zonal-resiliency {} \
--public-access None'.format(database_engine, resource_group, server_name, backup_retention,
sku_name, tier, storage_size, 'dbadmin', version, ha_value))
sku_name, tier, storage_size, 'dbadmin', version, zonal_resiliency_value))

basic_info = self.cmd('{} flexible-server show -g {} -n {}'.format(database_engine, resource_group, server_name)).get_output_in_json()
self.assertEqual(basic_info['name'], server_name)
Expand All @@ -158,6 +159,7 @@ def _test_flexible_server_mgmt(self, database_engine, resource_group):
self.assertEqual(basic_info['version'], version)
self.assertEqual(basic_info['storage']['storageSizeGb'], storage_size)
self.assertEqual(basic_info['backup']['backupRetentionDays'], backup_retention)
self.assertEqual(basic_info['highAvailability']['mode'], ha_value)

self.cmd('{} flexible-server db show -g {} -s {} -d {}'
.format(database_engine, resource_group, server_name, db_name), checks=[JMESPathCheck('name', db_name)])
Expand Down
35 changes: 28 additions & 7 deletions src/azure-cli/azure/cli/command_modules/rdbms/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ def _mysql_iops_validator(iops, auto_io_scaling, instance):


def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, server_name=None, database_name=None,
zone=None, standby_availability_zone=None, high_availability=None, subnet=None,
zone=None, standby_availability_zone=None, high_availability=None,
zonal_resiliency=None, allow_same_zone=False, subnet=None,
public_access=None, version=None, instance=None, geo_redundant_backup=None,
byok_identity=None, byok_key=None, backup_byok_identity=None, backup_byok_key=None,
auto_grow=None, performance_tier=None,
Expand Down Expand Up @@ -349,7 +350,8 @@ def pg_arguments_validator(db_context, location, tier, sku_name, storage_gb, ser
_pg_georedundant_backup_validator(geo_redundant_backup, geo_backup_supported)
_pg_storage_validator(storage_gb, sku_info, tier, storage_type, iops, throughput, instance)
_pg_sku_name_validator(sku_name, sku_info, tier, instance)
_pg_high_availability_validator(high_availability, standby_availability_zone, zone, tier, single_az, instance)
_pg_high_availability_validator(high_availability, zonal_resiliency, allow_same_zone,
standby_availability_zone, zone, tier, single_az, instance)
_pg_version_validator(version, list_location_capability_info['server_versions'])
pg_byok_validator(byok_identity, byok_key, backup_byok_identity, backup_byok_key, geo_redundant_backup, instance)
is_microsoft_entra_auth = bool(microsoft_entra_auth is not None and microsoft_entra_auth.lower() == 'enabled')
Expand Down Expand Up @@ -509,27 +511,46 @@ def _pg_version_validator(version, versions):
"maintain security, performance, and supportability.")


def _pg_high_availability_validator(high_availability, standby_availability_zone, zone, tier, single_az, instance):
def _pg_high_availability_validator(high_availability, zonal_resiliency, allow_same_zone,
standby_availability_zone, zone, tier, single_az, instance):
high_availability_enabled = (high_availability is not None and high_availability.lower() != 'disabled')
zonal_resiliency_enabled = (zonal_resiliency is not None and zonal_resiliency.lower() != 'disabled')
high_availability_zone_redundant = (high_availability_enabled and high_availability.lower() == 'zoneredundant')

if high_availability_enabled and zonal_resiliency_enabled:
raise ArgumentUsageError("Setting both --high-availability and --zonal-resiliency is not allowed. "
"Please set only --zonal-resiliency to move forward.")

if instance:
tier = instance.sku.tier if tier is None else tier
zone = instance.availability_zone if zone is None else zone

if high_availability is not None and high_availability.lower() != 'disabled':
if high_availability_enabled:
if tier == 'Burstable':
raise ArgumentUsageError("High availability is not supported for Burstable tier")
if single_az and high_availability.lower() == 'zoneredundant':
if single_az and high_availability_zone_redundant:
raise ArgumentUsageError("This region is single availability zone. "
"Zone redundant high availability is not supported "
"in a single availability zone region.")

if zonal_resiliency_enabled:
if tier == 'Burstable':
raise ArgumentUsageError("High availability is not supported for Burstable tier")
if single_az and allow_same_zone is False:
raise ArgumentUsageError("This region is single availability zone. "
"To proceed, please set --allow-same-zone.")

if standby_availability_zone:
if not high_availability or high_availability.lower() != 'zoneredundant':
raise ArgumentUsageError("You need to enable zone redundant high availability "
if not high_availability_zone_redundant or not zonal_resiliency_enabled:
raise ArgumentUsageError("You need to enable high availability by setting --zonal-resiliency to Enabled "
"to set standby availability zone.")
if zone == standby_availability_zone:
raise ArgumentUsageError("Your server is in availability zone {}. "
"The zone of the server cannot be same as the standby zone.".format(zone))

if allow_same_zone and not zonal_resiliency_enabled:
raise ArgumentUsageError("You can only set --allow-same-zone when --zonal-resiliency is Enabled.")


def _pg_georedundant_backup_validator(geo_redundant_backup, geo_backup_supported):
if (geo_redundant_backup and geo_redundant_backup.lower() == 'enabled') and not geo_backup_supported:
Expand Down