Skip to content

Commit 9e7385e

Browse files
author
Shilpa Jagannath
committed
rgw/multisite: check for both zonegroup and bucket level sync policies
when returning enotempty during bucket deletion Signed-off-by: Shilpa Jagannath <[email protected]>
1 parent 6020608 commit 9e7385e

File tree

3 files changed

+262
-8
lines changed

3 files changed

+262
-8
lines changed

src/rgw/driver/rados/rgw_rados.cc

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5682,11 +5682,18 @@ int RGWRados::delete_bucket(RGWBucketInfo& bucket_info, std::map<std::string, bu
56825682
// if there is bucket sync policy configured, by doing unordered
56835683
// listing with max_key=1. if objects are found, don't delete the bucket.
56845684
if (svc.zone->is_syncing_bucket_meta(bucket)) {
5685-
auto bs_policy = bucket_info.sync_policy;
5686-
if (bs_policy) {
5687-
ldpp_dout(dpp, 10) << "bucket policy exists. listing remote zones" << dendl;
5688-
const rgw_zone_id source_zone = svc.zone->get_zone_params().get_id();
5685+
// check if asymmetric replication policy exists either at zonegroup or bucket level
5686+
auto zg_sync_policy = svc.zone->get_zonegroup().sync_policy;
5687+
bool is_zg_policy_directional = zg_sync_policy.is_directional();
56895688

5689+
bool is_bucket_policy_directional = false;
5690+
auto bucket_sync_policy = bucket_info.sync_policy;
5691+
if (bucket_sync_policy) {
5692+
is_bucket_policy_directional = bucket_sync_policy->is_directional();
5693+
}
5694+
if (is_zg_policy_directional || is_bucket_policy_directional) {
5695+
ldpp_dout(dpp, 10) << "sync policy exists. listing remote zones" << dendl;
5696+
const rgw_zone_id source_zone = svc.zone->get_zone_params().get_id();
56905697
r = list_remote_buckets(dpp, driver, source_zone, bucket, y);
56915698
if (r == -ENOTEMPTY) {
56925699
ldpp_dout(dpp, 0) << "ERROR: cannot delete bucket. objects exist in the bucket on another zone " << dendl;

src/rgw/rgw_sync_policy.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,16 @@ struct rgw_sync_policy_info {
675675
return groups.empty();
676676
}
677677

678+
bool is_directional() const {
679+
for (auto& item : groups) {
680+
auto& group = item.second;
681+
if (!group.data_flow.directional.empty()) {
682+
return true;
683+
}
684+
}
685+
return false;
686+
}
687+
678688
void get_potential_related_buckets(const rgw_bucket& bucket,
679689
std::set<rgw_bucket> *sources,
680690
std::set<rgw_bucket> *dests) const;

src/test/rgw/rgw_multi/tests.py

Lines changed: 241 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2615,7 +2615,7 @@ def check_objects_not_exist(bucket, obj_arr):
26152615
check_object_not_exists(bucket, objname)
26162616

26172617
@attr('sync_policy')
2618-
def test_bucket_delete_with_sync_policy():
2618+
def test_bucket_delete_with_bucket_sync_policy_directional():
26192619

26202620
zonegroup = realm.master_zonegroup()
26212621
zonegroup_conns = ZonegroupConns(zonegroup)
@@ -2651,6 +2651,7 @@ def test_bucket_delete_with_sync_policy():
26512651
buckets.append(bucketA)
26522652
create_sync_policy_group(c1, "sync-bucket", "allowed", bucketA.name)
26532653
create_sync_group_flow_directional(c1, "sync-bucket", "sync-flow-bucket", zoneA.name, zoneB.name, bucketA.name)
2654+
#create_sync_group_flow_symmetrical(c1, "sync-bucket", "sync-flow-bucket", zones, bucketA.name)
26542655
create_sync_group_pipe(c1, "sync-bucket", "sync-pipe", zoneA.name, zoneB.name, bucketA.name)
26552656
set_sync_policy_group_status(c1, "sync-bucket", "enabled", bucketA.name)
26562657

@@ -2679,20 +2680,256 @@ def test_bucket_delete_with_sync_policy():
26792680
bucket = get_bucket(zcA, bucketA.name)
26802681
check_objects_not_exist(bucket, objnameB)
26812682

2682-
log.debug('deleting object')
2683+
log.debug('deleting object on zone A')
26832684
k = get_key(zcA, bucket, objnameA)
26842685
k.delete()
2685-
2686+
26862687
zone_bucket_checkpoint(zoneA, zoneB, bucketA.name)
2687-
2688+
26882689
# delete bucket on zoneA. it should fail to delete
26892690
log.debug('deleting bucket')
26902691
assert_raises(boto.exception.S3ResponseError, zcA.delete_bucket, bucketA.name)
26912692

26922693
assert check_all_buckets_exist(zcA, buckets)
26932694
assert check_all_buckets_exist(zcB, buckets)
2695+
2696+
log.debug('deleting object on zone B')
2697+
k = get_key(zcB, bucket, objnameB)
2698+
k.delete()
2699+
time.sleep(config.checkpoint_delay)
2700+
2701+
# retry deleting bucket after removing the object from zone B. should succeed
2702+
log.debug('retry deleting bucket')
2703+
zcA.delete_bucket(bucketA.name)
2704+
2705+
zonegroup_meta_checkpoint(zonegroup)
2706+
2707+
assert check_all_buckets_dont_exist(zcA, buckets)
2708+
assert check_all_buckets_dont_exist(zcB, buckets)
2709+
2710+
return
2711+
2712+
@attr('sync_policy')
2713+
def test_bucket_delete_with_bucket_sync_policy_symmetric():
2714+
2715+
zonegroup = realm.master_zonegroup()
2716+
zonegroup_conns = ZonegroupConns(zonegroup)
2717+
2718+
zonegroup_meta_checkpoint(zonegroup)
2719+
2720+
(zoneA, zoneB) = zonegroup.zones[0:2]
2721+
(zcA, zcB) = zonegroup_conns.zones[0:2]
2722+
2723+
c1 = zoneA.cluster
2724+
2725+
# configure sync policy
2726+
zones = zoneA.name + ',' + zoneB.name
2727+
c1.admin(['sync', 'policy', 'get'])
2728+
create_sync_policy_group(c1, "sync-group")
2729+
create_sync_group_flow_symmetrical(c1, "sync-group", "sync-flow", zones)
2730+
create_sync_group_pipe(c1, "sync-group", "sync-pipe", zones, zones)
2731+
set_sync_policy_group_status(c1, "sync-group", "allowed")
2732+
2733+
zonegroup.period.update(zoneA, commit=True)
2734+
get_sync_policy(c1)
2735+
2736+
"""
2737+
configure symmetrical policy at bucketA level with src and dest
2738+
zones specified to zoneA and zoneB resp.
2739+
"""
2740+
2741+
# configure sync policy for only bucketA and enable it
2742+
bucketA = create_zone_bucket(zcA)
2743+
buckets = []
2744+
buckets.append(bucketA)
2745+
create_sync_policy_group(c1, "sync-bucket", "allowed", bucketA.name)
2746+
create_sync_group_flow_symmetrical(c1, "sync-bucket", "sync-flow-bucket", zones, bucketA.name)
2747+
create_sync_group_pipe(c1, "sync-bucket", "sync-pipe", zones, zones, bucketA.name)
2748+
set_sync_policy_group_status(c1, "sync-bucket", "enabled", bucketA.name)
2749+
2750+
get_sync_policy(c1, bucketA.name)
2751+
2752+
zonegroup_meta_checkpoint(zonegroup)
2753+
2754+
# create bucketA and objects in zoneA and zoneB
2755+
objnameA = 'a'
2756+
objnameB = 'b'
2757+
2758+
# upload object in each zone and wait for sync.
2759+
k = new_key(zcA, bucketA, objnameA)
2760+
k.set_contents_from_string('foo')
2761+
k = new_key(zcB, bucketA, objnameB)
2762+
k.set_contents_from_string('foo')
2763+
2764+
zonegroup_meta_checkpoint(zonegroup)
2765+
zone_data_checkpoint(zoneB, zoneA)
2766+
2767+
log.debug('deleting object A')
2768+
k = get_key(zcA, bucketA, objnameA)
2769+
k.delete()
2770+
2771+
log.debug('deleting object B')
2772+
k = get_key(zcA, bucketA, objnameB)
2773+
k.delete()
2774+
2775+
zone_bucket_checkpoint(zoneA, zoneB, bucketA.name)
2776+
zone_data_checkpoint(zoneB, zoneA)
2777+
2778+
# delete bucket on zoneA.
2779+
log.debug('deleting bucket')
2780+
zcA.delete_bucket(bucketA.name)
2781+
zonegroup_meta_checkpoint(zonegroup)
2782+
2783+
assert check_all_buckets_dont_exist(zcA, buckets)
2784+
assert check_all_buckets_dont_exist(zcB, buckets)
2785+
return
2786+
2787+
@attr('sync_policy')
2788+
def test_bucket_delete_with_zonegroup_sync_policy_symmetric():
2789+
2790+
zonegroup = realm.master_zonegroup()
2791+
zonegroup_conns = ZonegroupConns(zonegroup)
2792+
2793+
zonegroup_meta_checkpoint(zonegroup)
2794+
2795+
(zoneA, zoneB) = zonegroup.zones[0:2]
2796+
(zcA, zcB) = zonegroup_conns.zones[0:2]
2797+
2798+
c1 = zoneA.cluster
2799+
2800+
# configure symmetric sync policy
2801+
zones = zoneA.name + ',' + zoneB.name
2802+
c1.admin(['sync', 'policy', 'get'])
2803+
create_sync_policy_group(c1, "sync-group")
2804+
create_sync_group_flow_symmetrical(c1, "sync-group", "sync-flow", zones)
2805+
create_sync_group_pipe(c1, "sync-group", "sync-pipe", zones, zones)
2806+
set_sync_policy_group_status(c1, "sync-group", "enabled")
2807+
2808+
zonegroup.period.update(zoneA, commit=True)
2809+
get_sync_policy(c1)
2810+
2811+
# configure sync policy for only bucketA and enable it
2812+
bucketA = create_zone_bucket(zcA)
2813+
buckets = []
2814+
buckets.append(bucketA)
2815+
2816+
time.sleep(config.checkpoint_delay)
2817+
zonegroup_meta_checkpoint(zonegroup)
2818+
2819+
# create bucketA and objects in zoneA and zoneB
2820+
objnameA = 'a'
2821+
objnameB = 'b'
2822+
2823+
# upload object in each zone and wait for sync.
2824+
k = new_key(zcA, bucketA, objnameA)
2825+
k.set_contents_from_string('foo')
2826+
k = new_key(zcB, bucketA, objnameB)
2827+
k.set_contents_from_string('foo')
2828+
2829+
zonegroup_meta_checkpoint(zonegroup)
2830+
zone_data_checkpoint(zoneB, zoneA)
2831+
2832+
log.debug('deleting object A')
2833+
k = get_key(zcA, bucketA, objnameA)
2834+
k.delete()
2835+
2836+
log.debug('deleting object B')
2837+
k = get_key(zcA, bucketA, objnameB)
2838+
k.delete()
2839+
2840+
zone_bucket_checkpoint(zoneA, zoneB, bucketA.name)
2841+
zone_data_checkpoint(zoneB, zoneA)
2842+
2843+
# delete bucket on zoneA.
2844+
log.debug('deleting bucket')
2845+
zcA.delete_bucket(bucketA.name)
2846+
zonegroup_meta_checkpoint(zonegroup)
2847+
2848+
assert check_all_buckets_dont_exist(zcA, buckets)
2849+
assert check_all_buckets_dont_exist(zcB, buckets)
26942850
return
26952851

2852+
@attr('sync_policy')
2853+
def test_bucket_delete_with_zonegroup_sync_policy_directional():
2854+
2855+
zonegroup = realm.master_zonegroup()
2856+
zonegroup_conns = ZonegroupConns(zonegroup)
2857+
2858+
zonegroup_meta_checkpoint(zonegroup)
2859+
2860+
(zoneA, zoneB) = zonegroup.zones[0:2]
2861+
(zcA, zcB) = zonegroup_conns.zones[0:2]
2862+
2863+
c1 = zoneA.cluster
2864+
2865+
# configure sync policy
2866+
zones = zoneA.name + ',' + zoneB.name
2867+
c1.admin(['sync', 'policy', 'get'])
2868+
create_sync_policy_group(c1, "sync-group")
2869+
create_sync_group_flow_directional(c1, "sync-group", "sync-flow1", zoneA.name, zoneB.name)
2870+
create_sync_group_pipe(c1, "sync-group", "sync-pipe", zoneA.name, zoneB.name)
2871+
set_sync_policy_group_status(c1, "sync-group", "enabled")
2872+
2873+
zonegroup.period.update(zoneA, commit=True)
2874+
get_sync_policy(c1)
2875+
2876+
# configure sync policy for only bucketA and enable it
2877+
bucketA = create_zone_bucket(zcA)
2878+
buckets = []
2879+
buckets.append(bucketA)
2880+
2881+
time.sleep(config.checkpoint_delay)
2882+
zonegroup_meta_checkpoint(zonegroup)
2883+
2884+
# create bucketA and objects in zoneA and zoneB
2885+
objnameA = 'a'
2886+
objnameB = 'b'
2887+
2888+
# upload object in each zone and wait for sync.
2889+
k = new_key(zcA, bucketA, objnameA)
2890+
k.set_contents_from_string('foo')
2891+
k = new_key(zcB, bucketA, objnameB)
2892+
k.set_contents_from_string('foo')
2893+
2894+
zonegroup_meta_checkpoint(zonegroup)
2895+
zone_data_checkpoint(zoneB, zoneA)
2896+
2897+
# verify that objnameA is synced to bucketA in zoneB
2898+
bucket = get_bucket(zcB, bucketA.name)
2899+
check_objects_exist(bucket, objnameA)
2900+
2901+
# verify that objnameB is not synced to bucketA in zoneA
2902+
bucket = get_bucket(zcA, bucketA.name)
2903+
check_objects_not_exist(bucket, objnameB)
2904+
2905+
log.debug('deleting object on zone A')
2906+
k = get_key(zcA, bucket, objnameA)
2907+
k.delete()
2908+
2909+
zone_bucket_checkpoint(zoneA, zoneB, bucketA.name)
2910+
2911+
# delete bucket on zoneA. it should fail to delete
2912+
log.debug('deleting bucket')
2913+
assert_raises(boto.exception.S3ResponseError, zcA.delete_bucket, bucketA.name)
2914+
2915+
assert check_all_buckets_exist(zcA, buckets)
2916+
assert check_all_buckets_exist(zcB, buckets)
2917+
2918+
# retry deleting bucket after removing the object from zone B. should succeed
2919+
log.debug('deleting object on zone B')
2920+
k = get_key(zcB, bucket, objnameB)
2921+
k.delete()
2922+
time.sleep(config.checkpoint_delay)
2923+
2924+
log.debug('retry deleting bucket')
2925+
zcA.delete_bucket(bucketA.name)
2926+
2927+
zonegroup_meta_checkpoint(zonegroup)
2928+
2929+
assert check_all_buckets_dont_exist(zcA, buckets)
2930+
assert check_all_buckets_dont_exist(zcB, buckets)
2931+
2932+
return
26962933

26972934
@attr('fails_with_rgw')
26982935
@attr('sync_policy')

0 commit comments

Comments
 (0)