Skip to content

Commit 6f7f22b

Browse files
authored
Merge pull request ceph#61211 from yuvalif/wip-yuval-logging-tenant
rgw/logging: add more validations to conf, cross tenant support and cleanup Reviewed-By: Adam Emerson <[email protected]>, Ali Masarwe <[email protected]>
2 parents ad76419 + fcfc50b commit 6f7f22b

File tree

13 files changed

+658
-165
lines changed

13 files changed

+658
-165
lines changed

doc/radosgw/bucket_logging.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ The log bucket can accumulate logs from multiple buckets. It is recommended to c
1515
a different "prefix" for each bucket, so that the logs of different buckets will be stored
1616
in different objects in the log bucket.
1717

18+
.. note::
19+
20+
- The log bucket must be created before enabling logging on a bucket
21+
- The log bucket cannot be the same as the bucket being logged
22+
- The log bucket cannot have logging enabled on it
23+
1824

1925
.. toctree::
2026
:maxdepth: 1
@@ -29,6 +35,7 @@ Adding a log object to the log bucket is done "lazily", meaning, that if no more
2935
remain outside of the log bucket even after the configured time has passed.
3036
To counter that, you can flush all logging objects on a given source bucket to log them,
3137
regardless if enough time passed or if no more records are written to the object.
38+
Flushing will happen automatically when logging is disabled on a bucket, its logging configuration is changed, or the bucket is deleted.
3239

3340
Standard
3441
````````
@@ -72,7 +79,7 @@ has the following format:
7279

7380
::
7481

75-
<prefix><bucket owner>/<source region>/<bucket name>/<year>/<month>/<day>/<year-month-day-hour-minute-second>-<16 bytes unique-id>
82+
<prefix><bucket owner>/<source region>/[tenant:]<bucket name>/<year>/<month>/<day>/<year-month-day-hour-minute-second>-<16 bytes unique-id>
7683

7784
For example:
7885

@@ -90,7 +97,7 @@ Journal
9097
minimum amount of data used for journaling bucket changes (this is a Ceph extension).
9198

9299
- bucket owner (or dash if empty)
93-
- bucket name (or dash if empty)
100+
- bucket name (or dash if empty). in the format: ``[tenant:]<bucket name>``
94101
- time in the following format: ``[day/month/year:hour:minute:second timezone]``
95102
- object key (or dash if empty)
96103
- operation in the following format: ``WEBSITE/REST.<HTTP method>.<resource>``
@@ -111,7 +118,7 @@ Standard
111118
based on `AWS Logging Record Format`_.
112119

113120
- bucket owner (or dash if empty)
114-
- bucket name (or dash if empty)
121+
- bucket name (or dash if empty). in the format: ``[tenant:]<bucket name>``
115122
- time
116123
- remote IP (not supported, always a dash)
117124
- user or account (or dash if empty)

src/rgw/driver/rados/rgw_sal_rados.cc

Lines changed: 76 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,10 @@ int RadosBucket::remove(const DoutPrefixProvider* dpp,
429429
ldpp_dout(dpp, -1) << "ERROR: unable to remove notifications from bucket. ret=" << ps_ret << dendl;
430430
}
431431

432+
if (ret = rgw::bucketlogging::bucket_deletion_cleanup(dpp, store, this, y); ret < 0) {
433+
ldpp_dout(dpp, 1) << "WARNING: could not cleanup bucket logging configuration and pending objects, ret = " << ret << dendl;
434+
}
435+
432436
ret = store->ctl()->bucket->unlink_bucket(rados, info.owner,
433437
info.bucket, y, dpp, false);
434438
if (ret < 0) {
@@ -1024,15 +1028,15 @@ int RadosBucket::remove_topics(RGWObjVersionTracker* objv_tracker,
10241028
objv_tracker, y);
10251029
}
10261030

1027-
int RadosBucket::get_logging_object_name(std::string& obj_name,
1028-
const std::string& prefix,
1029-
optional_yield y,
1031+
int RadosBucket::get_logging_object_name(std::string& obj_name,
1032+
const std::string& prefix,
1033+
optional_yield y,
10301034
const DoutPrefixProvider *dpp,
10311035
RGWObjVersionTracker* objv_tracker) {
10321036
rgw_pool data_pool;
10331037
const auto obj_name_oid = bucketlogging::object_name_oid(this, prefix);
10341038
if (!store->getRados()->get_obj_data_pool(get_placement_rule(), rgw_obj{get_key(), obj_name_oid}, &data_pool)) {
1035-
ldpp_dout(dpp, 1) << "failed to get data pool for bucket '" << get_name() <<
1039+
ldpp_dout(dpp, 1) << "ERROR: failed to get data pool for bucket '" << get_name() <<
10361040
"' when getting logging object name" << dendl;
10371041
return -EIO;
10381042
}
@@ -1048,23 +1052,23 @@ int RadosBucket::get_logging_object_name(std::string& obj_name,
10481052
nullptr,
10491053
nullptr);
10501054
if (ret < 0) {
1051-
ldpp_dout(dpp, 1) << "failed to get logging object name from '" << obj_name_oid << "'. ret = " << ret << dendl;
1055+
ldpp_dout(dpp, 1) << "ERROR: failed to get logging object name from '" << obj_name_oid << "'. ret = " << ret << dendl;
10521056
return ret;
10531057
}
10541058
obj_name = bl.to_str();
10551059
return 0;
10561060
}
10571061

1058-
int RadosBucket::set_logging_object_name(const std::string& obj_name,
1059-
const std::string& prefix,
1060-
optional_yield y,
1061-
const DoutPrefixProvider *dpp,
1062+
int RadosBucket::set_logging_object_name(const std::string& obj_name,
1063+
const std::string& prefix,
1064+
optional_yield y,
1065+
const DoutPrefixProvider *dpp,
10621066
bool new_obj,
10631067
RGWObjVersionTracker* objv_tracker) {
10641068
rgw_pool data_pool;
10651069
const auto obj_name_oid = bucketlogging::object_name_oid(this, prefix);
10661070
if (!store->getRados()->get_obj_data_pool(get_placement_rule(), rgw_obj{get_key(), obj_name_oid}, &data_pool)) {
1067-
ldpp_dout(dpp, 1) << "failed to get data pool for bucket '" << get_name() <<
1071+
ldpp_dout(dpp, 1) << "ERROR: failed to get data pool for bucket '" << get_name() <<
10681072
"' when setting logging object name" << dendl;
10691073
return -EIO;
10701074
}
@@ -1080,28 +1084,65 @@ int RadosBucket::set_logging_object_name(const std::string& obj_name,
10801084
y,
10811085
nullptr);
10821086
if (ret == -EEXIST) {
1083-
ldpp_dout(dpp, 20) << "race detected in initializing '" << obj_name_oid << "' with logging object name:'" << obj_name << "'. ret = " << ret << dendl;
1087+
ldpp_dout(dpp, 20) << "INFO: race detected in initializing '" << obj_name_oid << "' with logging object name:'" << obj_name << "'. ret = " << ret << dendl;
10841088
} else if (ret == -ECANCELED) {
1085-
ldpp_dout(dpp, 20) << "race detected in updating logging object name '" << obj_name << "' at '" << obj_name_oid << "'. ret = " << ret << dendl;
1089+
ldpp_dout(dpp, 20) << "INFO: race detected in updating logging object name '" << obj_name << "' at '" << obj_name_oid << "'. ret = " << ret << dendl;
10861090
} else if (ret < 0) {
1087-
ldpp_dout(dpp, 1) << "failed to set logging object name '" << obj_name << "' at '" << obj_name_oid << "'. ret = " << ret << dendl;
1091+
ldpp_dout(dpp, 1) << "ERROR: failed to set logging object name '" << obj_name << "' at '" << obj_name_oid << "'. ret = " << ret << dendl;
10881092
}
10891093
return ret;
10901094
}
10911095

1096+
int RadosBucket::remove_logging_object_name(const std::string& prefix,
1097+
optional_yield y,
1098+
const DoutPrefixProvider *dpp,
1099+
RGWObjVersionTracker* objv_tracker) {
1100+
rgw_pool data_pool;
1101+
const auto obj_name_oid = bucketlogging::object_name_oid(this, prefix);
1102+
if (!store->getRados()->get_obj_data_pool(get_placement_rule(), rgw_obj{get_key(), obj_name_oid}, &data_pool)) {
1103+
ldpp_dout(dpp, 1) << "ERROR: failed to get data pool for bucket '" << get_name() <<
1104+
"' when setting logging object name" << dendl;
1105+
return -EIO;
1106+
}
1107+
return rgw_delete_system_obj(dpp, store->svc()->sysobj,
1108+
data_pool,
1109+
obj_name_oid,
1110+
objv_tracker,
1111+
y);
1112+
}
1113+
10921114
std::string to_temp_object_name(const rgw::sal::Bucket* bucket, const std::string& obj_name) {
10931115
return fmt::format("{}__shadow_{}0",
10941116
bucket->get_bucket_id(),
10951117
obj_name);
10961118
}
10971119

1120+
int RadosBucket::remove_logging_object(const std::string& obj_name, optional_yield y, const DoutPrefixProvider *dpp) {
1121+
rgw_pool data_pool;
1122+
const rgw_obj head_obj{get_key(), obj_name};
1123+
const auto placement_rule = get_placement_rule();
1124+
1125+
if (!store->getRados()->get_obj_data_pool(placement_rule, head_obj, &data_pool)) {
1126+
ldpp_dout(dpp, 1) << "ERROR: failed to get data pool for bucket '" << get_name() <<
1127+
"' when deleting logging object" << dendl;
1128+
return -EIO;
1129+
}
1130+
1131+
const auto temp_obj_name = to_temp_object_name(this, obj_name);
1132+
return rgw_delete_system_obj(dpp, store->svc()->sysobj,
1133+
data_pool,
1134+
temp_obj_name,
1135+
nullptr,
1136+
y);
1137+
}
1138+
10981139
int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yield y, const DoutPrefixProvider *dpp) {
10991140
rgw_pool data_pool;
11001141
const rgw_obj head_obj{get_key(), obj_name};
11011142
const auto placement_rule = get_placement_rule();
11021143

11031144
if (!store->getRados()->get_obj_data_pool(placement_rule, head_obj, &data_pool)) {
1104-
ldpp_dout(dpp, 1) << "failed to get data pool for bucket '" << get_name() <<
1145+
ldpp_dout(dpp, 1) << "ERROR: failed to get data pool for bucket '" << get_name() <<
11051146
"' when comitting logging object" << dendl;
11061147
return -EIO;
11071148
}
@@ -1110,7 +1151,6 @@ int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yie
11101151
std::map<string, bufferlist> obj_attrs;
11111152
ceph::real_time mtime;
11121153
bufferlist bl_data;
1113-
// TODO: this is needed only for etag calculation
11141154
if (const auto ret = rgw_get_system_obj(store->svc()->sysobj,
11151155
data_pool,
11161156
temp_obj_name,
@@ -1120,10 +1160,13 @@ int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yie
11201160
y,
11211161
dpp,
11221162
&obj_attrs,
1123-
nullptr); ret < 0) {
1124-
ldpp_dout(dpp, 1) << "faild to read logging data when comitting to object '" << temp_obj_name
1163+
nullptr); ret < 0 && ret != -ENOENT) {
1164+
ldpp_dout(dpp, 1) << "ERROR: failed to read logging data when comitting object '" << temp_obj_name
11251165
<< ". error: " << ret << dendl;
11261166
return ret;
1167+
} else if (ret == -ENOENT) {
1168+
ldpp_dout(dpp, 1) << "WARNING: temporary logging object '" << temp_obj_name << "' does not exists" << dendl;
1169+
return 0;
11271170
}
11281171

11291172
uint64_t size = bl_data.length();
@@ -1137,21 +1180,21 @@ int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yie
11371180
nullptr, // no special placment for tail
11381181
get_key(),
11391182
head_obj); ret < 0) {
1140-
ldpp_dout(dpp, 1) << "failed to create manifest when comitting logging object. error: " <<
1183+
ldpp_dout(dpp, 1) << "ERROR: failed to create manifest when comitting logging object. error: " <<
11411184
ret << dendl;
11421185
return ret;
11431186
}
11441187

11451188
if (const auto ret = manifest_gen.create_next(size); ret < 0) {
1146-
ldpp_dout(dpp, 1) << "failed to add object to manifest when comitting logging object. error: " <<
1189+
ldpp_dout(dpp, 1) << "ERROR: failed to add object to manifest when comitting logging object. error: " <<
11471190
ret << dendl;
11481191
return ret;
11491192
}
11501193

11511194
if (const auto expected_temp_obj = manifest_gen.get_cur_obj(store->getRados());
11521195
temp_obj_name != expected_temp_obj.oid) {
11531196
// TODO: cleanup temporary object, commit would never succeed
1154-
ldpp_dout(dpp, 1) << "temporary logging object name mismatch: '" <<
1197+
ldpp_dout(dpp, 1) << "ERROR: temporary logging object name mismatch: '" <<
11551198
temp_obj_name << "' != '" << expected_temp_obj.oid << "'" << dendl;
11561199
return -EINVAL;
11571200
}
@@ -1182,11 +1225,11 @@ int RadosBucket::commit_logging_object(const std::string& obj_name, optional_yie
11821225
const req_context rctx{dpp, y, nullptr};
11831226
jspan_context trace{false, false};
11841227
if (const auto ret = head_obj_wop.write_meta(0, size, obj_attrs, rctx, trace); ret < 0) {
1185-
ldpp_dout(dpp, 1) << "failed to commit logging object '" << temp_obj_name <<
1186-
"' to bucket id '" << get_bucket_id() <<"'. error: " << ret << dendl;
1228+
ldpp_dout(dpp, 1) << "ERROR: failed to commit logging object '" << temp_obj_name <<
1229+
"' to bucket id '" << get_info().bucket <<"'. error: " << ret << dendl;
11871230
return ret;
11881231
}
1189-
ldpp_dout(dpp, 20) << "committed logging object '" << temp_obj_name <<
1232+
ldpp_dout(dpp, 20) << "INFO: committed logging object '" << temp_obj_name <<
11901233
"' with size of " << size << " bytes, to bucket '" << get_key() << "' as '" <<
11911234
obj_name << "'" << dendl;
11921235
return 0;
@@ -1204,30 +1247,30 @@ void bucket_logging_completion(rados_completion_t completion, void* args) {
12041247
auto* aio_comp = reinterpret_cast<librados::AioCompletionImpl*>(completion);
12051248
std::unique_ptr<BucketLoggingCompleteArg> logging_args(reinterpret_cast<BucketLoggingCompleteArg*>(args));
12061249
if (aio_comp->get_return_value() < 0) {
1207-
ldout(logging_args->cct, 1) << "failed to complete append to logging object '" << logging_args->obj_name <<
1250+
ldout(logging_args->cct, 1) << "ERROR: failed to complete append to logging object '" << logging_args->obj_name <<
12081251
"'. ret = " << aio_comp->get_return_value() << dendl;
12091252
} else {
1210-
ldout(logging_args->cct, 20) << "wrote " << logging_args->size << " bytes to logging object '" <<
1253+
ldout(logging_args->cct, 20) << "INFO: wrote " << logging_args->size << " bytes to logging object '" <<
12111254
logging_args->obj_name << "'" << dendl;
12121255
}
12131256
}
12141257

1215-
int RadosBucket::write_logging_object(const std::string& obj_name,
1216-
const std::string& record,
1217-
optional_yield y,
1258+
int RadosBucket::write_logging_object(const std::string& obj_name,
1259+
const std::string& record,
1260+
optional_yield y,
12181261
const DoutPrefixProvider *dpp,
12191262
bool async_completion) {
12201263
const auto temp_obj_name = to_temp_object_name(this, obj_name);
12211264
rgw_pool data_pool;
12221265
rgw_obj obj{get_key(), obj_name};
12231266
if (!store->getRados()->get_obj_data_pool(get_placement_rule(), obj, &data_pool)) {
1224-
ldpp_dout(dpp, 1) << "failed to get data pool for bucket '" << get_name() <<
1267+
ldpp_dout(dpp, 1) << "ERROR: failed to get data pool for bucket '" << get_name() <<
12251268
"' when writing logging object" << dendl;
12261269
return -EIO;
12271270
}
12281271
librados::IoCtx io_ctx;
12291272
if (const auto ret = rgw_init_ioctx(dpp, store->getRados()->get_rados_handle(), data_pool, io_ctx); ret < 0) {
1230-
ldpp_dout(dpp, 1) << "failed to get IO context for logging object from data pool:" << data_pool.to_str() << dendl;
1273+
ldpp_dout(dpp, 1) << "ERROR: failed to get IO context for logging object from data pool:" << data_pool.to_str() << dendl;
12311274
return -EIO;
12321275
}
12331276
bufferlist bl;
@@ -1242,7 +1285,7 @@ int RadosBucket::write_logging_object(const std::string& obj_name,
12421285
auto arg = std::make_unique<BucketLoggingCompleteArg>(temp_obj_name, record.length(), store->ctx());
12431286
completion->set_complete_callback(arg.get(), bucket_logging_completion);
12441287
if (const auto ret = io_ctx.aio_operate(temp_obj_name, completion.get(), &op); ret < 0) {
1245-
ldpp_dout(dpp, 1) << "failed to append to logging object '" << temp_obj_name <<
1288+
ldpp_dout(dpp, 1) << "ERROR: failed to append to logging object '" << temp_obj_name <<
12461289
"'. ret = " << ret << dendl;
12471290
return ret;
12481291
}
@@ -1251,11 +1294,11 @@ int RadosBucket::write_logging_object(const std::string& obj_name,
12511294
return 0;
12521295
}
12531296
if (const auto ret = rgw_rados_operate(dpp, io_ctx, temp_obj_name, &op, y); ret < 0) {
1254-
ldpp_dout(dpp, 1) << "failed to append to logging object '" << temp_obj_name <<
1297+
ldpp_dout(dpp, 1) << "ERROR: failed to append to logging object '" << temp_obj_name <<
12551298
"'. ret = " << ret << dendl;
12561299
return ret;
12571300
}
1258-
ldpp_dout(dpp, 20) << "wrote " << record.length() << " bytes to logging object '" <<
1301+
ldpp_dout(dpp, 20) << "INFO: wrote " << record.length() << " bytes to logging object '" <<
12591302
temp_obj_name << "'" << dendl;
12601303
return 0;
12611304
}

src/rgw/driver/rados/rgw_sal_rados.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -780,18 +780,23 @@ class RadosBucket : public StoreBucket {
780780
optional_yield y, const DoutPrefixProvider *dpp) override;
781781
int remove_topics(RGWObjVersionTracker* objv_tracker,
782782
optional_yield y, const DoutPrefixProvider *dpp) override;
783-
int get_logging_object_name(std::string& obj_name,
784-
const std::string& prefix,
785-
optional_yield y,
786-
const DoutPrefixProvider *dpp,
783+
int get_logging_object_name(std::string& obj_name,
784+
const std::string& prefix,
785+
optional_yield y,
786+
const DoutPrefixProvider *dpp,
787+
RGWObjVersionTracker* objv_tracker) override;
788+
int set_logging_object_name(const std::string& obj_name,
789+
const std::string& prefix,
790+
optional_yield y,
791+
const DoutPrefixProvider *dpp,
792+
bool new_obj,
787793
RGWObjVersionTracker* objv_tracker) override;
788-
int set_logging_object_name(const std::string& obj_name,
789-
const std::string& prefix,
790-
optional_yield y,
791-
const DoutPrefixProvider *dpp,
792-
bool new_obj,
794+
int remove_logging_object_name(const std::string& prefix,
795+
optional_yield y,
796+
const DoutPrefixProvider *dpp,
793797
RGWObjVersionTracker* objv_tracker) override;
794798
int commit_logging_object(const std::string& obj_name, optional_yield y, const DoutPrefixProvider *dpp) override;
799+
int remove_logging_object(const std::string& obj_name, optional_yield y, const DoutPrefixProvider *dpp) override;
795800
int write_logging_object(const std::string& obj_name, const std::string& record, optional_yield y, const DoutPrefixProvider *dpp, bool async_completion) override;
796801

797802
private:

0 commit comments

Comments
 (0)