Skip to content

Commit 2c4b718

Browse files
committed
rgw: skip versioned entries to non-versioned buckets and vice-versa
As instance field is preserved while replicating, this can make confusion for versioned buckets having non-versioned objects and non-versioned buckets having versioned objects. Fixes: https://tracker.ceph.com/issues/70486 Signed-off-by: Seena Fallah <[email protected]>
1 parent 7e47dee commit 2c4b718

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

src/rgw/driver/rados/rgw_data_sync.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4520,6 +4520,14 @@ class RGWBucketSyncSingleEntryCR : public RGWCoroutine {
45204520
tn->log(0, "entry with empty obj name, skipping");
45214521
goto done;
45224522
}
4523+
4524+
// make sure versioned object only lands on versioned bucket and non-versioned object only lands on non-versioned bucket
4525+
if (key.instance.empty() == sync_pipe.dest_bucket_info.versioned()) {
4526+
set_status("skipping entry due to versioning mismatch");
4527+
tn->log(0, SSTR("skipping entry due to versioning mismatch: " << key));
4528+
goto done;
4529+
}
4530+
45234531
if (error_injection &&
45244532
rand() % 10000 < cct->_conf->rgw_sync_data_inject_err_probability * 10000.0) {
45254533
tn->log(0, SSTR(": injecting data sync error on key=" << key.name));

src/test/rgw/rgw_multi/tests.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3946,3 +3946,99 @@ def test_bucket_replicaion_reject_objectlock_identical():
39463946
}]
39473947
})
39483948
assert e.response['ResponseMetadata']['HTTPStatusCode'] == 400
3949+
3950+
@allow_bucket_replication
3951+
def test_bucket_replication_non_versioned_to_versioned():
3952+
zonegroup = realm.master_zonegroup()
3953+
zonegroup_conns = ZonegroupConns(zonegroup)
3954+
3955+
source = zonegroup_conns.non_account_rw_zones[0]
3956+
dest = zonegroup_conns.non_account_rw_zones[1]
3957+
3958+
source_bucket = source.create_bucket(gen_bucket_name())
3959+
dest_bucket = dest.create_bucket(gen_bucket_name())
3960+
zonegroup_meta_checkpoint(zonegroup)
3961+
3962+
# create replication configuration
3963+
response = source.s3_client.put_bucket_replication(
3964+
Bucket=source_bucket.name,
3965+
ReplicationConfiguration={
3966+
'Role': '',
3967+
'Rules': [
3968+
{
3969+
'ID': 'rule1',
3970+
'Status': 'Enabled',
3971+
'Destination': {
3972+
'Bucket': f'arn:aws:s3:::{dest_bucket.name}',
3973+
}
3974+
}
3975+
]
3976+
}
3977+
)
3978+
assert response['ResponseMetadata']['HTTPStatusCode'] == 200
3979+
zonegroup_meta_checkpoint(zonegroup)
3980+
3981+
# enable versioning on destination bucket
3982+
dest.s3_client.put_bucket_versioning(
3983+
Bucket=dest_bucket.name,
3984+
VersioningConfiguration={'Status': 'Enabled'}
3985+
)
3986+
zonegroup_meta_checkpoint(zonegroup)
3987+
3988+
# upload an object and wait for sync.
3989+
objname = 'dummy'
3990+
k = new_key(source, source_bucket, objname)
3991+
k.set_contents_from_string('foo')
3992+
zone_data_checkpoint(dest.zone, source.zone)
3993+
3994+
# check that object not exists in destination bucket
3995+
e = assert_raises(ClientError, dest.s3_client.get_object, Bucket=dest_bucket.name, Key=objname)
3996+
assert e.response['Error']['Code'] == 'NoSuchKey'
3997+
3998+
@allow_bucket_replication
3999+
def test_bucket_replication_versioned_to_non_versioned():
4000+
zonegroup = realm.master_zonegroup()
4001+
zonegroup_conns = ZonegroupConns(zonegroup)
4002+
4003+
source = zonegroup_conns.non_account_rw_zones[0]
4004+
dest = zonegroup_conns.non_account_rw_zones[1]
4005+
4006+
source_bucket = source.create_bucket(gen_bucket_name())
4007+
dest_bucket = dest.create_bucket(gen_bucket_name())
4008+
zonegroup_meta_checkpoint(zonegroup)
4009+
4010+
# create replication configuration
4011+
response = source.s3_client.put_bucket_replication(
4012+
Bucket=source_bucket.name,
4013+
ReplicationConfiguration={
4014+
'Role': '',
4015+
'Rules': [
4016+
{
4017+
'ID': 'rule1',
4018+
'Status': 'Enabled',
4019+
'Destination': {
4020+
'Bucket': f'arn:aws:s3:::{dest_bucket.name}',
4021+
}
4022+
}
4023+
]
4024+
}
4025+
)
4026+
assert response['ResponseMetadata']['HTTPStatusCode'] == 200
4027+
zonegroup_meta_checkpoint(zonegroup)
4028+
4029+
# enable versioning on source bucket
4030+
source.s3_client.put_bucket_versioning(
4031+
Bucket=source_bucket.name,
4032+
VersioningConfiguration={'Status': 'Enabled'}
4033+
)
4034+
zonegroup_meta_checkpoint(zonegroup)
4035+
4036+
# upload an object and wait for sync.
4037+
objname = 'dummy'
4038+
k = new_key(source, source_bucket, objname)
4039+
k.set_contents_from_string('foo')
4040+
zone_data_checkpoint(dest.zone, source.zone)
4041+
4042+
# check that object not exists in destination bucket
4043+
e = assert_raises(ClientError, dest.s3_client.get_object, Bucket=dest_bucket.name, Key=objname)
4044+
assert e.response['Error']['Code'] == 'NoSuchKey'

0 commit comments

Comments
 (0)