@@ -6804,6 +6804,254 @@ def __init__(self, name, group, location):
68046804 JMESPathCheck ('length(@)' , 0 )
68056805 ])
68066806
6807+ # create 2 servers in the same resource group, and 1 server in a different resource group
6808+ @ResourceGroupPreparer (parameter_name = "resource_group_1" ,
6809+ parameter_name_for_location = "resource_group_location_1" )
6810+ @ResourceGroupPreparer (parameter_name = "resource_group_2" ,
6811+ parameter_name_for_location = "resource_group_location_2" )
6812+ @SqlServerPreparer (parameter_name = "server_name_1" ,
6813+ resource_group_parameter_name = "resource_group_1" ,
6814+ location = 'northeurope' )
6815+ @SqlServerPreparer (parameter_name = "server_name_2" ,
6816+ resource_group_parameter_name = "resource_group_1" ,
6817+ location = 'uksouth' )
6818+ @SqlServerPreparer (parameter_name = "server_name_3" ,
6819+ resource_group_parameter_name = "resource_group_2" ,
6820+ location = 'swedencentral' )
6821+ def test_sql_failover_group_mgmt_multiple_partners (self ,
6822+ resource_group_1 , resource_group_location_1 ,
6823+ resource_group_2 , resource_group_location_2 ,
6824+ server_name_1 , server_name_2 , server_name_3 ):
6825+ # helper class so that it's clear which servers are in which groups
6826+ class ServerInfo : # pylint disable=too-few-public-methods
6827+ def __init__ (self , name , group , location ):
6828+ self .name = name
6829+ self .group = group
6830+ self .location = location
6831+
6832+ from azure .cli .core .commands .client_factory import get_subscription_id
6833+
6834+ s1 = ServerInfo (server_name_1 , resource_group_1 , resource_group_location_1 )
6835+ s2 = ServerInfo (server_name_2 , resource_group_1 , resource_group_location_1 )
6836+ s3 = ServerInfo (server_name_3 , resource_group_2 , resource_group_location_2 )
6837+
6838+ failover_group_name = "fgclitest-multiplepartner123789"
6839+
6840+ database_name = "db1"
6841+
6842+ server2_id = "/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Sql/servers/{}" .format (
6843+ get_subscription_id (self .cli_ctx ),
6844+ resource_group_1 ,
6845+ server_name_2 )
6846+
6847+ server3_id = "/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Sql/servers/{}" .format (
6848+ get_subscription_id (self .cli_ctx ),
6849+ resource_group_2 ,
6850+ server_name_3 )
6851+
6852+ # Create database on primary server
6853+ self .cmd ('sql db create -g {} --server {} --name {}'
6854+ .format (s1 .group , s1 .name , database_name ),
6855+ checks = [
6856+ JMESPathCheck ('resourceGroup' , s1 .group ),
6857+ JMESPathCheck ('name' , database_name )
6858+ ])
6859+
6860+ # Create Failover Group
6861+ self .cmd (
6862+ 'sql failover-group create -n {} -g {} -s {} --partner-resource-group {} --partner-server {} --failover-policy Automatic --grace-period 2 --partner-server-ids {} {} --readonly-failover-policy Enabled'
6863+ .format (failover_group_name , s1 .group , s1 .name , s2 .group , s2 .name , server2_id , server3_id ),
6864+ checks = [
6865+ JMESPathCheck ('name' , failover_group_name ),
6866+ JMESPathCheck ('resourceGroup' , s1 .group ),
6867+ JMESPathCheck ('partnerServers[0].id' , server2_id ),
6868+ JMESPathCheck ('partnerServers[1].id' , server3_id ),
6869+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Automatic' ),
6870+ JMESPathCheck ('readWriteEndpoint.failoverWithDataLossGracePeriodMinutes' , 120 ),
6871+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Enabled' ),
6872+ JMESPathCheck ('readOnlyEndpoint.targetServer' , server2_id ),
6873+ JMESPathCheck ('length(databases)' , 0 )
6874+ ])
6875+
6876+ # List of all failover groups on the primary server
6877+ self .cmd ('sql failover-group list -g {} -s {}'
6878+ .format (s1 .group , s1 .name ),
6879+ checks = [
6880+ JMESPathCheck ('length(@)' , 1 ),
6881+ JMESPathCheck ('[0].name' , failover_group_name ),
6882+ JMESPathCheck ('[0].replicationRole' , 'Primary' )
6883+ ])
6884+
6885+ # Get Failover Group on a partner server and check if role is secondary
6886+ self .cmd ('sql failover-group show -g {} -s {} -n {}'
6887+ .format (s2 .group , s2 .name , failover_group_name ),
6888+ checks = [
6889+ JMESPathCheck ('name' , failover_group_name ),
6890+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Automatic' ),
6891+ JMESPathCheck ('readWriteEndpoint.failoverWithDataLossGracePeriodMinutes' , 120 ),
6892+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Enabled' ),
6893+ JMESPathCheck ('replicationRole' , 'Secondary' ),
6894+ JMESPathCheck ('length(databases)' , 0 )
6895+ ])
6896+
6897+ self .cmd ('sql failover-group show -g {} -s {} -n {}'
6898+ .format (s3 .group , s3 .name , failover_group_name ),
6899+ checks = [
6900+ JMESPathCheck ('name' , failover_group_name ),
6901+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Automatic' ),
6902+ JMESPathCheck ('readWriteEndpoint.failoverWithDataLossGracePeriodMinutes' , 120 ),
6903+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Enabled' ),
6904+ JMESPathCheck ('replicationRole' , 'Secondary' ),
6905+ JMESPathCheck ('length(databases)' , 0 )
6906+ ])
6907+
6908+ if self .in_recording :
6909+ time .sleep (60 )
6910+
6911+ # Update Failover Group
6912+ self .cmd ('sql failover-group update -g {} -s {} -n {} --grace-period 3 --add-db {} --readonly-endpoint-target {} --readonly-failover-policy Disabled'
6913+ .format (s1 .group , s1 .name , failover_group_name , database_name , server3_id ),
6914+ checks = [
6915+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Automatic' ),
6916+ JMESPathCheck ('readWriteEndpoint.failoverWithDataLossGracePeriodMinutes' , 180 ),
6917+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Disabled' ),
6918+ JMESPathCheck ('readOnlyEndpoint.targetServer' , server3_id ),
6919+ JMESPathCheck ('length(databases)' , 1 )
6920+ ])
6921+
6922+ # Check if properties got propagated to secondary server
6923+ self .cmd ('sql failover-group show -g {} -s {} -n {}'
6924+ .format (s2 .group , s2 .name , failover_group_name ),
6925+ checks = [
6926+ JMESPathCheck ('name' , failover_group_name ),
6927+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Automatic' ),
6928+ JMESPathCheck ('readWriteEndpoint.failoverWithDataLossGracePeriodMinutes' , 180 ),
6929+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Disabled' ),
6930+ JMESPathCheck ('readOnlyEndpoint.targetServer' , server3_id ),
6931+ JMESPathCheck ('replicationRole' , 'Secondary' ),
6932+ JMESPathCheck ('length(databases)' , 1 )
6933+ ])
6934+
6935+ self .cmd ('sql failover-group show -g {} -s {} -n {}'
6936+ .format (s3 .group , s3 .name , failover_group_name ),
6937+ checks = [
6938+ JMESPathCheck ('name' , failover_group_name ),
6939+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Automatic' ),
6940+ JMESPathCheck ('readWriteEndpoint.failoverWithDataLossGracePeriodMinutes' , 180 ),
6941+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Disabled' ),
6942+ JMESPathCheck ('readOnlyEndpoint.targetServer' , server3_id ),
6943+ JMESPathCheck ('replicationRole' , 'Secondary' ),
6944+ JMESPathCheck ('length(databases)' , 1 )
6945+ ])
6946+
6947+ # Check if database is created on partner side
6948+ self .cmd ('sql db list -g {} -s {}'
6949+ .format (s2 .group , s2 .name ),
6950+ checks = [
6951+ JMESPathCheck ('length(@)' , 2 )
6952+ ])
6953+
6954+ self .cmd ('sql db list -g {} -s {}'
6955+ .format (s3 .group , s3 .name ),
6956+ checks = [
6957+ JMESPathCheck ('length(@)' , 2 )
6958+ ])
6959+
6960+ if self .in_recording :
6961+ time .sleep (60 )
6962+
6963+ # Check secondary type parameter functionality
6964+ self ._test_failover_group_with_secondary_type (s1 , s2 , failover_group_name , "Standby" )
6965+
6966+ self ._test_failover_group_with_secondary_type (s1 , s2 , failover_group_name , "Geo" )
6967+
6968+ # Update Failover Group failover policy to Manual
6969+ self .cmd ('sql failover-group update -g {} -s {} -n {} --failover-policy Manual'
6970+ .format (s1 .group , s1 .name , failover_group_name ),
6971+ checks = [
6972+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Manual' ),
6973+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Disabled' ),
6974+ JMESPathCheck ('length(databases)' , 1 )
6975+ ])
6976+
6977+ # Failover failover group from secondary server and then fail back
6978+ self ._test_failover_group_failover (s1 , s2 , failover_group_name , self .FailoverType .planned )
6979+
6980+ self ._test_failover_group_failover (s1 , s2 , failover_group_name , self .FailoverType .forced )
6981+
6982+ self ._test_failover_group_failover (s1 , s2 , failover_group_name , self .FailoverType .hybrid )
6983+
6984+ self ._test_failover_group_failover (s1 , s3 , failover_group_name , self .FailoverType .planned )
6985+
6986+ self ._test_failover_group_failover (s1 , s3 , failover_group_name , self .FailoverType .forced )
6987+
6988+ self ._test_failover_group_failover (s1 , s3 , failover_group_name , self .FailoverType .hybrid )
6989+
6990+ # Failover failover group from primary server (No-op)
6991+ self ._test_failover_group_failover_from_primary (s1 , s2 , failover_group_name , self .FailoverType .planned )
6992+
6993+ self ._test_failover_group_failover_from_primary (s1 , s2 , failover_group_name , self .FailoverType .forced )
6994+
6995+ self ._test_failover_group_failover_from_primary (s1 , s2 , failover_group_name , self .FailoverType .hybrid )
6996+
6997+ # Remove database from failover group
6998+ self .cmd ('sql failover-group update -g {} -s {} -n {} --remove-db {}'
6999+ .format (s1 .group , s1 .name , failover_group_name , database_name ),
7000+ checks = [
7001+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Manual' ),
7002+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Disabled' ),
7003+ JMESPathCheck ('length(databases)' , 0 )
7004+ ])
7005+
7006+ # Check if database got removed
7007+ self .cmd ('sql db show -g {} -s {} -n {}'
7008+ .format (s2 .group , s2 .name , database_name ),
7009+ checks = [
7010+ JMESPathCheck ('[0].failoverGroupId' , 'None' )
7011+ ])
7012+
7013+ self .cmd ('sql db show -g {} -s {} -n {}'
7014+ .format (s3 .group , s3 .name , database_name ),
7015+ checks = [
7016+ JMESPathCheck ('[0].failoverGroupId' , 'None' )
7017+ ])
7018+
7019+ # Remove partner server from failover group
7020+ self .cmd ('sql failover-group update -g {} -s {} -n {} --partner-server-ids {}'
7021+ .format (s1 .group , s1 .name , failover_group_name , server3_id ),
7022+ checks = [
7023+ JMESPathCheck ('partnerServers[0].id' , server3_id ),
7024+ JMESPathCheck ('readWriteEndpoint.failoverPolicy' , 'Automatic' ),
7025+ JMESPathCheck ('readWriteEndpoint.failoverWithDataLossGracePeriodMinutes' , 180 ),
7026+ JMESPathCheck ('readOnlyEndpoint.failoverPolicy' , 'Disabled' ),
7027+ JMESPathCheck ('readOnlyEndpoint.targetServer' , server3_id ),
7028+ JMESPathCheck ('length(databases)' , 1 )
7029+ ])
7030+
7031+ # Check partner server was removed
7032+ self .cmd ('sql failover-group list -g {} -s {}'
7033+ .format (s2 .group , s2 .name ),
7034+ checks = [
7035+ JMESPathCheck ('length(@)' , 0 )
7036+ ])
7037+
7038+ # Drop failover group
7039+ self .cmd ('sql failover-group delete -g {} -s {} -n {}'
7040+ .format (s1 .group , s1 .name , failover_group_name ))
7041+
7042+ # Check if failover group really got dropped
7043+ self .cmd ('sql failover-group list -g {} -s {}'
7044+ .format (s1 .group , s1 .name ),
7045+ checks = [
7046+ JMESPathCheck ('length(@)' , 0 )
7047+ ])
7048+
7049+ self .cmd ('sql failover-group list -g {} -s {}'
7050+ .format (s3 .group , s3 .name ),
7051+ checks = [
7052+ JMESPathCheck ('length(@)' , 0 )
7053+ ])
7054+
68077055class SqlVirtualClusterMgmtScenarioTest (ScenarioTest ):
68087056 @ManagedInstancePreparer ()
68097057 def test_sql_virtual_cluster_mgmt (self , mi , rg ):
0 commit comments