Skip to content

Commit 826d493

Browse files
committed
rgw: skip replication from lock enabled buckets to lock disbaled buckets
replicating lock enabled objects require the destination bucket to have object lock enabled. Fixes: https://tracker.ceph.com/issues/70486 Signed-off-by: Seena Fallah <[email protected]>
1 parent 2c4b718 commit 826d493

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

src/rgw/driver/rados/rgw_data_sync.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4527,6 +4527,12 @@ class RGWBucketSyncSingleEntryCR : public RGWCoroutine {
45274527
tn->log(0, SSTR("skipping entry due to versioning mismatch: " << key));
45284528
goto done;
45294529
}
4530+
// if object lock is enabled on either, the other should follow as well
4531+
if (sync_pipe.source_bucket_info.obj_lock_enabled() != sync_pipe.dest_bucket_info.obj_lock_enabled()) {
4532+
set_status("skipping entry due to object lock mismatch");
4533+
tn->log(0, SSTR("skipping entry due to object lock mismatch: " << key));
4534+
goto done;
4535+
}
45304536

45314537
if (error_injection &&
45324538
rand() % 10000 < cct->_conf->rgw_sync_data_inject_err_probability * 10000.0) {

src/test/rgw/rgw_multi/tests.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4042,3 +4042,131 @@ def test_bucket_replication_versioned_to_non_versioned():
40424042
# check that object not exists in destination bucket
40434043
e = assert_raises(ClientError, dest.s3_client.get_object, Bucket=dest_bucket.name, Key=objname)
40444044
assert e.response['Error']['Code'] == 'NoSuchKey'
4045+
4046+
@allow_bucket_replication
4047+
def test_bucket_replication_lock_enabled_to_lock_disabled():
4048+
zonegroup = realm.master_zonegroup()
4049+
zonegroup_conns = ZonegroupConns(zonegroup)
4050+
4051+
source = zonegroup_conns.non_account_rw_zones[0]
4052+
dest = zonegroup_conns.non_account_rw_zones[1]
4053+
4054+
source_bucket_name = gen_bucket_name()
4055+
source.create_bucket(source_bucket_name)
4056+
# enabled versioning
4057+
source.s3_client.put_bucket_versioning(
4058+
Bucket=source_bucket_name,
4059+
VersioningConfiguration={'Status': 'Enabled'}
4060+
)
4061+
dest_bucket = dest.create_bucket(gen_bucket_name())
4062+
# enabled versioning
4063+
dest.s3_client.put_bucket_versioning(
4064+
Bucket=dest_bucket.name,
4065+
VersioningConfiguration={'Status': 'Enabled'}
4066+
)
4067+
zonegroup_meta_checkpoint(zonegroup)
4068+
4069+
# create replication configuration
4070+
source.s3_client.put_bucket_replication(
4071+
Bucket=source_bucket_name,
4072+
ReplicationConfiguration={
4073+
'Role': '',
4074+
'Rules': [{
4075+
'ID': 'rule1',
4076+
'Status': 'Enabled',
4077+
'Destination': {
4078+
'Bucket': f'arn:aws:s3:::{dest_bucket.name}',
4079+
}
4080+
}]
4081+
}
4082+
)
4083+
zonegroup_meta_checkpoint(zonegroup)
4084+
4085+
# enable object lock on source bucket
4086+
source.s3_client.put_object_lock_configuration(
4087+
Bucket=source_bucket_name,
4088+
ObjectLockConfiguration={
4089+
'ObjectLockEnabled': 'Enabled',
4090+
'Rule': {
4091+
'DefaultRetention': {
4092+
'Mode': 'GOVERNANCE',
4093+
'Days': 1
4094+
}
4095+
}
4096+
}
4097+
)
4098+
zonegroup_meta_checkpoint(zonegroup)
4099+
4100+
# upload an object and wait for sync.
4101+
objname = 'dummy'
4102+
k = new_key(source, source_bucket_name, objname)
4103+
k.set_contents_from_string('foo')
4104+
zone_data_checkpoint(dest.zone, source.zone)
4105+
4106+
# check that object does not exist in destination bucket
4107+
e = assert_raises(ClientError, dest.s3_client.get_object, Bucket=dest_bucket.name, Key=objname)
4108+
assert e.response['Error']['Code'] == 'NoSuchKey'
4109+
4110+
@allow_bucket_replication
4111+
def test_bucket_replication_lock_disabled_to_lock_enabled():
4112+
zonegroup = realm.master_zonegroup()
4113+
zonegroup_conns = ZonegroupConns(zonegroup)
4114+
4115+
source = zonegroup_conns.non_account_rw_zones[0]
4116+
dest = zonegroup_conns.non_account_rw_zones[1]
4117+
4118+
source_bucket = source.create_bucket(gen_bucket_name())
4119+
# enabled versioning
4120+
source.s3_client.put_bucket_versioning(
4121+
Bucket=source_bucket.name,
4122+
VersioningConfiguration={'Status': 'Enabled'}
4123+
)
4124+
dest_bucket_name = gen_bucket_name()
4125+
dest.create_bucket(dest_bucket_name)
4126+
# enabled versioning
4127+
dest.s3_client.put_bucket_versioning(
4128+
Bucket=dest_bucket_name,
4129+
VersioningConfiguration={'Status': 'Enabled'}
4130+
)
4131+
zonegroup_meta_checkpoint(zonegroup)
4132+
4133+
# create replication configuration
4134+
source.s3_client.put_bucket_replication(
4135+
Bucket=source_bucket.name,
4136+
ReplicationConfiguration={
4137+
'Role': '',
4138+
'Rules': [{
4139+
'ID': 'rule1',
4140+
'Status': 'Enabled',
4141+
'Destination': {
4142+
'Bucket': f'arn:aws:s3:::{dest_bucket_name}',
4143+
}
4144+
}]
4145+
}
4146+
)
4147+
zonegroup_meta_checkpoint(zonegroup)
4148+
4149+
# enable object lock on destination bucket
4150+
dest.s3_client.put_object_lock_configuration(
4151+
Bucket=dest_bucket_name,
4152+
ObjectLockConfiguration={
4153+
'ObjectLockEnabled': 'Enabled',
4154+
'Rule': {
4155+
'DefaultRetention': {
4156+
'Mode': 'GOVERNANCE',
4157+
'Days': 1
4158+
}
4159+
}
4160+
}
4161+
)
4162+
zonegroup_meta_checkpoint(zonegroup)
4163+
4164+
# upload an object and wait for sync.
4165+
objname = 'dummy'
4166+
k = new_key(source, source_bucket.name, objname)
4167+
k.set_contents_from_string('foo')
4168+
zone_data_checkpoint(dest.zone, source.zone)
4169+
4170+
# check that object does not exist in destination bucket
4171+
e = assert_raises(ClientError, dest.s3_client.get_object, Bucket=dest_bucket_name, Key=objname)
4172+
assert e.response['Error']['Code'] == 'NoSuchKey'

0 commit comments

Comments
 (0)