@@ -1038,6 +1038,177 @@ def test_003_object_storage_and_secondary_block(self):
10381038 zaza_model .block_until_unit_wl_status (self .secondary_rgw_unit ,
10391039 'active' )
10401040
1041+ def test_004_multisite_directional_sync_policy (self ):
1042+ """Verify Multisite Directional Sync Policy."""
1043+ # Skip multisite tests if not compatible with bundle.
1044+ if not self .multisite :
1045+ logging .info ('Skipping multisite sync policy verification' )
1046+ return
1047+
1048+ container_name = 'zaza-container'
1049+ obj_data = 'Test data from Zaza'
1050+ obj_name = 'testfile'
1051+
1052+ logging .info ('Verifying multisite directional sync policy' )
1053+
1054+ # Set default sync policy to "allowed", which allows buckets to sync,
1055+ # but the sync is disabled by default in the zone group. Also, set the
1056+ # secondary zone sync policy flow type policy to "directional".
1057+ zaza_model .set_application_config (
1058+ self .primary_rgw_app ,
1059+ {
1060+ "sync-policy-state" : "allowed" ,
1061+ }
1062+ )
1063+ zaza_model .set_application_config (
1064+ self .secondary_rgw_app ,
1065+ {
1066+ "sync-policy-flow-type" : "directional" ,
1067+ }
1068+ )
1069+ zaza_model .wait_for_unit_idle (self .secondary_rgw_unit )
1070+ zaza_model .wait_for_unit_idle (self .primary_rgw_unit )
1071+
1072+ # Setup multisite relation.
1073+ multisite_relation = zaza_model .get_relation_id (
1074+ self .primary_rgw_app , self .secondary_rgw_app ,
1075+ remote_interface_name = 'secondary'
1076+ )
1077+ if multisite_relation is None :
1078+ logging .info ('Configuring Multisite' )
1079+ self .configure_rgw_apps_for_multisite ()
1080+ zaza_model .add_relation (
1081+ self .primary_rgw_app ,
1082+ self .primary_rgw_app + ":primary" ,
1083+ self .secondary_rgw_app + ":secondary"
1084+ )
1085+ zaza_model .block_until_unit_wl_status (
1086+ self .secondary_rgw_unit , "waiting"
1087+ )
1088+ zaza_model .block_until_unit_wl_status (
1089+ self .primary_rgw_unit , "active"
1090+ )
1091+ zaza_model .block_until_unit_wl_status (
1092+ self .secondary_rgw_unit , "active"
1093+ )
1094+ zaza_model .wait_for_unit_idle (self .secondary_rgw_unit )
1095+ zaza_model .wait_for_unit_idle (self .primary_rgw_unit )
1096+
1097+ logging .info ('Waiting for Data and Metadata to Synchronize' )
1098+ self .wait_for_status (self .secondary_rgw_app , is_primary = False )
1099+ self .wait_for_status (self .primary_rgw_app , is_primary = True )
1100+
1101+ # Create bucket on primary RGW zone.
1102+ logging .info ('Creating bucket on primary zone' )
1103+ primary_endpoint = self .get_rgw_endpoint (self .primary_rgw_unit )
1104+ self .assertNotEqual (primary_endpoint , None )
1105+
1106+ access_key , secret_key = self .get_client_keys ()
1107+ primary_client = boto3 .resource ("s3" ,
1108+ verify = False ,
1109+ endpoint_url = primary_endpoint ,
1110+ aws_access_key_id = access_key ,
1111+ aws_secret_access_key = secret_key )
1112+ primary_client .Bucket (container_name ).create ()
1113+
1114+ # Enable sync on the bucket.
1115+ logging .info ('Enabling sync on the bucket from the primary zone' )
1116+ zaza_model .run_action_on_leader (
1117+ self .primary_rgw_app ,
1118+ 'enable-buckets-sync' ,
1119+ action_params = {
1120+ 'buckets' : container_name ,
1121+ },
1122+ raise_on_failure = True ,
1123+ )
1124+
1125+ # Check that sync cannot be enabled using secondary Juju RGW app.
1126+ with self .assertRaises (zaza_model .ActionFailed ):
1127+ zaza_model .run_action_on_leader (
1128+ self .secondary_rgw_app ,
1129+ 'enable-buckets-sync' ,
1130+ action_params = {
1131+ 'buckets' : container_name ,
1132+ },
1133+ raise_on_failure = True ,
1134+ )
1135+
1136+ # Perform IO on primary zone bucket.
1137+ logging .info ('Performing IO on primary zone bucket' )
1138+ primary_object_one = primary_client .Object (
1139+ container_name ,
1140+ obj_name
1141+ )
1142+ primary_object_one .put (Body = obj_data )
1143+
1144+ # Verify that the object is replicated to the secondary zone.
1145+ logging .info ('Verifying that the object is replicated to the '
1146+ 'secondary zone' )
1147+ secondary_endpoint = self .get_rgw_endpoint (self .secondary_rgw_unit )
1148+ self .assertNotEqual (secondary_endpoint , None )
1149+
1150+ secondary_client = boto3 .resource ("s3" ,
1151+ verify = False ,
1152+ endpoint_url = secondary_endpoint ,
1153+ aws_access_key_id = access_key ,
1154+ aws_secret_access_key = secret_key )
1155+ secondary_data = self .fetch_rgw_object (
1156+ secondary_client ,
1157+ container_name ,
1158+ obj_name
1159+ )
1160+ self .assertEqual (secondary_data , obj_data )
1161+
1162+ # Write a second object to the secondary zone bucket.
1163+ logging .info ('Writing a second object to the secondary zone bucket, '
1164+ 'which should not be replicated to the primary zone' )
1165+ secondary_obj_name = "{}-secondary" .format (obj_name )
1166+ secondary_object_two = secondary_client .Object (
1167+ container_name ,
1168+ secondary_obj_name
1169+ )
1170+ secondary_object_two .put (Body = obj_data )
1171+
1172+ # Verify that second object is not replicated to the primary zone.
1173+ logging .info ('Verifying that the object is not replicated to the '
1174+ 'primary zone' )
1175+ with self .assertRaises (botocore .exceptions .ClientError ):
1176+ self .fetch_rgw_object (
1177+ primary_client ,
1178+ container_name ,
1179+ obj_data
1180+ )
1181+
1182+ # Cleanup.
1183+ logging .info ('Cleaning up buckets after test case' )
1184+ self .purge_bucket (self .primary_rgw_app , container_name )
1185+ self .purge_bucket (self .secondary_rgw_app , container_name )
1186+
1187+ logging .info ('Waiting for Data and Metadata to Synchronize' )
1188+ self .wait_for_status (self .secondary_rgw_app , is_primary = False )
1189+ self .wait_for_status (self .primary_rgw_app , is_primary = True )
1190+
1191+ # Set multisite sync policy state to "enabled", and sync policy flow
1192+ # to "symmetrical" on the secondary RGW zone. This enables
1193+ # bidirectional sync between the zones (which is the default
1194+ # behaviour without multisite sync policies configured).
1195+ logging .info ('Setting sync policy state to "enabled", and sync '
1196+ 'policy flow to "symmetrical" on the secondary RGW zone' )
1197+ zaza_model .set_application_config (
1198+ self .primary_rgw_app ,
1199+ {
1200+ "sync-policy-state" : "enabled" ,
1201+ }
1202+ )
1203+ zaza_model .set_application_config (
1204+ self .secondary_rgw_app ,
1205+ {
1206+ "sync-policy-flow-type" : "symmetrical" ,
1207+ }
1208+ )
1209+ zaza_model .wait_for_unit_idle (self .secondary_rgw_unit )
1210+ zaza_model .wait_for_unit_idle (self .primary_rgw_unit )
1211+
10411212 def test_100_migration_and_multisite_failover (self ):
10421213 """Perform multisite migration and verify failover."""
10431214 container_name = 'zaza-container'
@@ -1139,6 +1310,10 @@ def test_100_migration_and_multisite_failover(self):
11391310 'Body'
11401311 ].read ().decode ('UTF-8' )
11411312
1313+ # Wait for Sites to be syncronised.
1314+ self .wait_for_status (self .primary_rgw_app , is_primary = False )
1315+ self .wait_for_status (self .secondary_rgw_app , is_primary = True )
1316+
11421317 # Recovery scenario, reset ceph-rgw as primary.
11431318 self .promote_rgw_to_primary (self .primary_rgw_app )
11441319 self .wait_for_status (self .primary_rgw_app , is_primary = True )
0 commit comments