Skip to content

Commit bcd79d2

Browse files
yuvalifcbodley
authored andcommitted
rgw/notifications: handle migration state between v1 and v2
test instructions: https://gist.github.com/yuvalif/21449e301732b719cd1ed97c3eeeabb2 * during migration all topic and notification operations must fail with HTTP error code 503 * read operations should return the values of the v1 topics and notifications * sending notifications should continue based on v1 values Signed-off-by: Yuval Lifshitz <[email protected]>
1 parent 5b2ae72 commit bcd79d2

File tree

10 files changed

+68
-10
lines changed

10 files changed

+68
-10
lines changed

src/rgw/driver/rados/rgw_notify.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,8 @@ static inline bool notification_match(reservation_t& res,
988988
const RGWObjTags* req_tags)
989989
{
990990
rgw_pubsub_bucket_topics bucket_topics;
991-
if (all_zonegroups_support(site, zone_features::notification_v2)) {
991+
if (all_zonegroups_support(site, zone_features::notification_v2) &&
992+
res.store->stat_topics_v1(res.user_tenant, res.yield, res.dpp) == -ENOENT) {
992993
auto ret = 0;
993994
if (!res.s) {
994995
// for non S3-request caller (e.g., lifecycle, ObjectSync), bucket attrs
@@ -1064,7 +1065,7 @@ static inline bool notification_match(reservation_t& res,
10641065
ldpp_dout(res.dpp, 1)
10651066
<< "INFO: failed to load topic: " << topic_cfg.name
10661067
<< ". error: " << ret
1067-
<< " while storing the persistent notification event" << dendl;
1068+
<< " while resrving persistent notification event" << dendl;
10681069
if (ret == -ENOENT) {
10691070
// either the topic is deleted but the corresponding notification still
10701071
// exist or in v2 mode the notification could have synced first but

src/rgw/driver/rados/rgw_sal_rados.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "rgw_acl_s3.h"
3636
#include "rgw_aio.h"
3737
#include "rgw_aio_throttle.h"
38+
#include "rgw_tools.h"
3839
#include "rgw_tracer.h"
3940

4041
#include "rgw_zone.h"
@@ -1117,6 +1118,10 @@ int RadosStore::read_topics(const std::string& tenant, rgw_pubsub_topics& topics
11171118
return 0;
11181119
}
11191120

1121+
int RadosStore::stat_topics_v1(const std::string& tenant, optional_yield y, const DoutPrefixProvider *dpp) {
1122+
return rgw_stat_system_obj(dpp, svc()->sysobj, svc()->zone->get_zone_params().log_pool, topics_oid(tenant), nullptr, nullptr, y, nullptr);
1123+
}
1124+
11201125
int RadosStore::write_topics(const std::string& tenant, const rgw_pubsub_topics& topics, RGWObjVersionTracker* objv_tracker,
11211126
optional_yield y, const DoutPrefixProvider *dpp) {
11221127
bufferlist bl;

src/rgw/driver/rados/rgw_sal_rados.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ class RadosStore : public StoreDriver {
160160
std::string& _req_id, optional_yield y) override;
161161
int read_topics(const std::string& tenant, rgw_pubsub_topics& topics, RGWObjVersionTracker* objv_tracker,
162162
optional_yield y, const DoutPrefixProvider *dpp) override;
163+
int stat_topics_v1(const std::string& tenant, optional_yield y, const DoutPrefixProvider *dpp) override;
163164
int write_topics(const std::string& tenant, const rgw_pubsub_topics& topics, RGWObjVersionTracker* objv_tracker,
164165
optional_yield y, const DoutPrefixProvider *dpp) override;
165166
int remove_topics(const std::string& tenant, RGWObjVersionTracker* objv_tracker,

src/rgw/rgw_admin.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10628,7 +10628,8 @@ int main(int argc, const char **argv)
1062810628
cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
1062910629
return -ret;
1063010630
}
10631-
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2)) {
10631+
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2) &&
10632+
driver->stat_topics_v1(tenant, null_yield, dpp()) == -ENOENT) {
1063210633
ret = get_bucket_notifications(dpp(), bucket.get(), result);
1063310634
if (ret < 0) {
1063410635
cerr << "ERROR: could not get topics: " << cpp_strerror(-ret)
@@ -10667,7 +10668,8 @@ int main(int argc, const char **argv)
1066710668
continue;
1066810669
}
1066910670
std::set<std::string> subscribed_buckets;
10670-
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2)) {
10671+
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2) &&
10672+
driver->stat_topics_v1(tenant, null_yield, dpp()) == -ENOENT) {
1067110673
ret = driver->get_bucket_topic_mapping(topic, subscribed_buckets,
1067210674
null_yield, dpp());
1067310675
if (ret < 0) {
@@ -10709,7 +10711,8 @@ int main(int argc, const char **argv)
1070910711
cerr << "ERROR: could not get topic: " << cpp_strerror(-ret) << std::endl;
1071010712
return -ret;
1071110713
}
10712-
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2)) {
10714+
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2) &&
10715+
driver->stat_topics_v1(tenant, null_yield, dpp()) == -ENOENT) {
1071310716
show_topics_info_v2(topic, subscribed_buckets, formatter.get());
1071410717
} else {
1071510718
encode_json("topic", topic, formatter.get());
@@ -10733,7 +10736,8 @@ int main(int argc, const char **argv)
1073310736
return -ret;
1073410737
}
1073510738
rgw_pubsub_bucket_topics bucket_topics;
10736-
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2)) {
10739+
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2) &&
10740+
driver->stat_topics_v1(tenant, null_yield, dpp()) == -ENOENT) {
1073710741
ret = get_bucket_notifications(dpp(), bucket.get(), bucket_topics);
1073810742
if (ret < 0) {
1073910743
cerr << "ERROR: could not get bucket notifications: "
@@ -10799,6 +10803,11 @@ int main(int argc, const char **argv)
1079910803
}
1080010804

1080110805
if (rgw::all_zonegroups_support(*site, rgw::zone_features::notification_v2)) {
10806+
if (ret = driver->stat_topics_v1(tenant, null_yield, dpp()); ret != -ENOENT) {
10807+
cerr << "WARNING: " << (ret == 0 ? "topic migration in process" : "cannot determine topic migration status. ret = " + std::to_string(ret))
10808+
<< ". please try again later" << std::endl;
10809+
return -ret;
10810+
}
1080210811
ret = remove_notification_v2(dpp(), driver, bucket.get(), notification_id,
1080310812
null_yield);
1080410813
} else {

src/rgw/rgw_common.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ rgw_http_errors rgw_http_s3_errors({
127127
{ ERR_INTERNAL_ERROR, {500, "InternalError" }},
128128
{ ERR_NOT_IMPLEMENTED, {501, "NotImplemented" }},
129129
{ ERR_SERVICE_UNAVAILABLE, {503, "ServiceUnavailable"}},
130+
{ EBUSY, {503, "ServiceUnavailable"}},
130131
{ ERR_RATE_LIMITED, {503, "SlowDown"}},
131132
{ ERR_ZERO_IN_URL, {400, "InvalidRequest" }},
132133
{ ERR_NO_SUCH_TAG_SET, {404, "NoSuchTagSet"}},

src/rgw/rgw_pubsub.cc

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -539,11 +539,12 @@ int RGWPubSub::get_topics(const DoutPrefixProvider* dpp,
539539
rgw_pubsub_topics& result, std::string& next_marker,
540540
optional_yield y) const
541541
{
542-
if (!use_notification_v2) {
542+
if (!use_notification_v2 || driver->stat_topics_v1(tenant, y, dpp) != -ENOENT) {
543+
// in case of v1 or during migration we use v1 topics
543544
// v1 returns all topics, ignoring marker/max_items
544545
return read_topics_v1(dpp, result, nullptr, y);
545546
}
546-
547+
547548
// TODO: prefix filter on 'tenant:'
548549
void* handle = NULL;
549550
int ret = driver->meta_list_keys_init(dpp, "topic", start_marker, &handle);
@@ -623,6 +624,13 @@ int RGWPubSub::Bucket::write_topics(const DoutPrefixProvider *dpp, const rgw_pub
623624
RGWObjVersionTracker *objv_tracker,
624625
optional_yield y) const
625626
{
627+
if (ps.use_notification_v2) {
628+
if (const auto ret = ps.driver->stat_topics_v1(bucket->get_tenant(), y, dpp); ret != -ENOENT) {
629+
ldpp_dout(dpp, 1) << "WARNING: " << (ret == 0 ? "topic migration in process" : "cannot determine topic migration status. ret = " + std::to_string(ret))
630+
<< ". please try again later" << dendl;
631+
return -ERR_SERVICE_UNAVAILABLE;
632+
}
633+
}
626634
const int ret = bucket->write_topics(topics, objv_tracker, y, dpp);
627635
if (ret < 0) {
628636
ldpp_dout(dpp, 1) << "ERROR: failed to write bucket topics info: ret=" << ret << dendl;
@@ -637,7 +645,8 @@ int RGWPubSub::get_topic(const DoutPrefixProvider* dpp,
637645
rgw_pubsub_topic& result,
638646
optional_yield y,
639647
std::set<std::string>* subscribed_buckets) const {
640-
if (use_notification_v2) {
648+
if (use_notification_v2 && driver->stat_topics_v1(tenant, y, dpp) == -ENOENT) {
649+
// in case of v1 or during migration we use v1 topics
641650
int ret = driver->read_topic_v2(name, tenant, result, nullptr, y, dpp);
642651
if (ret < 0) {
643652
ldpp_dout(dpp, 1) << "failed to read topic info for name: " << name
@@ -962,6 +971,11 @@ int RGWPubSub::create_topic(const DoutPrefixProvider* dpp,
962971
const std::string& policy_text,
963972
optional_yield y) const {
964973
if (use_notification_v2) {
974+
if (const auto ret = driver->stat_topics_v1(tenant, y, dpp); ret != -ENOENT) {
975+
ldpp_dout(dpp, 1) << "WARNING: " << (ret == 0 ? "topic migration in process" : "cannot determine topic migration status. ret = " + std::to_string(ret))
976+
<< ". please try again later" << dendl;
977+
return -ERR_SERVICE_UNAVAILABLE;
978+
}
965979
rgw_pubsub_topic new_topic;
966980
new_topic.user = user;
967981
new_topic.name = name;
@@ -994,6 +1008,7 @@ int RGWPubSub::create_topic(const DoutPrefixProvider* dpp,
9941008
ldpp_dout(dpp, 1) << "ERROR: failed to write topics info: ret=" << ret << dendl;
9951009
return ret;
9961010
}
1011+
ldpp_dout(dpp, 1) << "INFO: successfully created v1 topic" << dendl;
9971012

9981013
return 0;
9991014
}
@@ -1025,6 +1040,11 @@ int RGWPubSub::remove_topic_v2(const DoutPrefixProvider* dpp,
10251040
int RGWPubSub::remove_topic(const DoutPrefixProvider *dpp, const std::string& name, optional_yield y) const
10261041
{
10271042
if (use_notification_v2) {
1043+
if (const auto ret = driver->stat_topics_v1(tenant, y, dpp); ret != -ENOENT) {
1044+
ldpp_dout(dpp, 1) << "WARNING: " << (ret == 0 ? "topic migration in process" : "cannot determine topic migration status. ret = " + std::to_string(ret))
1045+
<< ". please try again later" << dendl;
1046+
return -ERR_SERVICE_UNAVAILABLE;
1047+
}
10281048
return remove_topic_v2(dpp, name, y);
10291049
}
10301050
RGWObjVersionTracker objv_tracker;

src/rgw/rgw_rest_pubsub.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,13 @@ void RGWPSCreateNotifOp::execute_v2(optional_yield y) {
11521152
}
11531153
}
11541154

1155+
if (const auto ret = driver->stat_topics_v1(s->bucket_tenant, y, this); ret != -ENOENT) {
1156+
ldpp_dout(this, 1) << "WARNING: " << (ret == 0 ? "topic migration in process" : "cannot determine topic migration status. ret = " + std::to_string(ret))
1157+
<< ". please try again later" << dendl;
1158+
op_ret = -ERR_SERVICE_UNAVAILABLE;
1159+
return;
1160+
}
1161+
11551162
std::unique_ptr<rgw::sal::Bucket> bucket;
11561163
op_ret = driver->load_bucket(this, rgw_bucket(s->bucket_tenant, s->bucket_name),
11571164
&bucket, y);
@@ -1381,6 +1388,13 @@ void RGWPSDeleteNotifOp::execute_v2(optional_yield y) {
13811388
}
13821389
}
13831390

1391+
if (const auto ret = driver->stat_topics_v1(s->bucket_tenant, y, this); ret != -ENOENT) {
1392+
ldpp_dout(this, 1) << "WARNING: " << (ret == 0 ? "topic migration in process" : "cannot determine topic migration status. ret = " + std::to_string(ret))
1393+
<< ". please try again later" << dendl;
1394+
op_ret = -ERR_SERVICE_UNAVAILABLE;
1395+
return;
1396+
}
1397+
13841398
std::unique_ptr<rgw::sal::Bucket> bucket;
13851399
op_ret = driver->load_bucket(this, rgw_bucket(s->bucket_tenant, s->bucket_name),
13861400
&bucket, y);
@@ -1459,7 +1473,8 @@ void RGWPSListNotifsOp::execute(optional_yield y) {
14591473

14601474
// get all topics on a bucket
14611475
rgw_pubsub_bucket_topics bucket_topics;
1462-
if (rgw::all_zonegroups_support(*s->penv.site, rgw::zone_features::notification_v2)) {
1476+
if (rgw::all_zonegroups_support(*s->penv.site, rgw::zone_features::notification_v2) &&
1477+
driver->stat_topics_v1(s->bucket_tenant, y, this) == -ENOENT) {
14631478
op_ret = get_bucket_notifications(this, bucket.get(), bucket_topics);
14641479
} else {
14651480
const RGWPubSub ps(driver, s->owner.id.tenant);

src/rgw/rgw_sal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ class Driver {
308308
/** Read the topic config entry into @a data and (optionally) @a objv_tracker */
309309
virtual int read_topics(const std::string& tenant, rgw_pubsub_topics& topics, RGWObjVersionTracker* objv_tracker,
310310
optional_yield y, const DoutPrefixProvider *dpp) = 0;
311+
/** check if the v1 topics object exists */
312+
virtual int stat_topics_v1(const std::string& tenant, optional_yield y, const DoutPrefixProvider *dpp) = 0;
311313
/** Write @a info and (optionally) @a objv_tracker into the config */
312314
virtual int write_topics(const std::string& tenant, const rgw_pubsub_topics& topics, RGWObjVersionTracker* objv_tracker,
313315
optional_yield y, const DoutPrefixProvider *dpp) = 0;

src/rgw/rgw_sal_filter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ class FilterDriver : public Driver {
186186
optional_yield y, const DoutPrefixProvider *dpp) override {
187187
return next->read_topics(tenant, topics, objv_tracker, y, dpp);
188188
}
189+
int stat_topics_v1(const std::string& tenant, optional_yield y, const DoutPrefixProvider *dpp) override {
190+
return next->stat_topics_v1(tenant, y, dpp);
191+
}
189192
int write_topics(const std::string& tenant, const rgw_pubsub_topics& topics, RGWObjVersionTracker* objv_tracker,
190193
optional_yield y, const DoutPrefixProvider *dpp) override {
191194
return next->write_topics(tenant, topics, objv_tracker, y, dpp);

src/rgw/rgw_sal_store.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class StoreDriver : public Driver {
3030

3131
int read_topics(const std::string& tenant, rgw_pubsub_topics& topics, RGWObjVersionTracker* objv_tracker,
3232
optional_yield y, const DoutPrefixProvider *dpp) override {return -EOPNOTSUPP;}
33+
int stat_topics_v1(const std::string& tenant, optional_yield y, const DoutPrefixProvider *dpp) override {return -EOPNOTSUPP;}
3334
int write_topics(const std::string& tenant, const rgw_pubsub_topics& topics, RGWObjVersionTracker* objv_tracker,
3435
optional_yield y, const DoutPrefixProvider *dpp) override {return -ENOENT;}
3536
int remove_topics(const std::string& tenant, RGWObjVersionTracker* objv_tracker,

0 commit comments

Comments
 (0)