From d951ee5f5b10b8ae7032772dc3d6938032067f2c Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Mon, 21 Mar 2016 14:51:58 -0400 Subject: [PATCH] rgw: 'period commit' supplies user-readable error messages Signed-off-by: Casey Bodley --- src/rgw/rgw_admin.cc | 2 +- src/rgw/rgw_rados.cc | 25 ++++++++++++++++--------- src/rgw/rgw_rados.h | 3 ++- src/rgw/rgw_rest_realm.cc | 16 ++++++++++++---- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 29967ddb543ce..6239dc603a7f8 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -1381,7 +1381,7 @@ static int commit_period(RGWRealm& realm, RGWPeriod& period, return ret; } // the master zone can commit locally - ret = period.commit(realm, current_period); + ret = period.commit(realm, current_period, cerr); if (ret < 0) { cerr << "failed to commit period: " << cpp_strerror(-ret) << std::endl; } diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 717778881ce79..8f8a67d11709d 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -1273,27 +1273,32 @@ int RGWPeriod::update_sync_status() return 0; } -int RGWPeriod::commit(RGWRealm& realm, const RGWPeriod& current_period) +int RGWPeriod::commit(RGWRealm& realm, const RGWPeriod& current_period, + std::ostream& error_stream) { ldout(cct, 20) << __func__ << " realm " << realm.get_id() << " period " << current_period.get_id() << dendl; // gateway must be in the master zone to commit if (master_zone != store->get_zone_params().get_id()) { - ldout(cct, 0) << "period commit on zone " << store->get_zone_params().get_id() - << ", not period's master zone " << master_zone << dendl; + error_stream << "Cannot commit period on zone " + << store->get_zone_params().get_id() << ", it must be sent to " + "the period's master zone " << master_zone << '.' << std::endl; return -EINVAL; } // period predecessor must match current period if (predecessor_uuid != current_period.get_id()) { - ldout(cct, 0) << "period predecessor " << predecessor_uuid + error_stream << "Period predecessor " << predecessor_uuid << " does not match current period " << current_period.get_id() - << dendl; + << ". Use 'period pull' to get the latest period from the master, " + "reapply your changes, and try again." << std::endl; return -EINVAL; } // realm epoch must be 1 greater than current period if (realm_epoch != current_period.get_realm_epoch() + 1) { - ldout(cct, 0) << "period's realm epoch " << realm_epoch + error_stream << "Period's realm epoch " << realm_epoch << " does not come directly after current realm epoch " - << current_period.get_realm_epoch() << dendl; + << current_period.get_realm_epoch() << ". Use 'realm pull' to get the " + "latest realm and period from the master zone, reapply your changes, " + "and try again." << std::endl; return -EINVAL; } // did the master zone change? @@ -1325,8 +1330,10 @@ int RGWPeriod::commit(RGWRealm& realm, const RGWPeriod& current_period) } // period must be based on current epoch if (epoch != current_period.get_epoch()) { - ldout(cct, 0) << "period epoch " << epoch << " does not match " - "predecessor epoch " << current_period.get_epoch() << dendl; + error_stream << "Period epoch " << epoch << " does not match " + "predecessor epoch " << current_period.get_epoch() + << ". Use 'period pull' to get the latest epoch from the master zone, " + "reapply your changes, and try again." << std::endl; return -EINVAL; } // set period as next epoch diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index b95c838a47c52..963399621d8e4 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -1469,7 +1469,8 @@ public: int update(); // commit a staging period; only for use on master zone - int commit(RGWRealm& realm, const RGWPeriod ¤t_period); + int commit(RGWRealm& realm, const RGWPeriod ¤t_period, + std::ostream& error_stream); void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); diff --git a/src/rgw/rgw_rest_realm.cc b/src/rgw/rgw_rest_realm.cc index 488c0cc682859..652735fea29c8 100644 --- a/src/rgw/rgw_rest_realm.cc +++ b/src/rgw/rgw_rest_realm.cc @@ -17,6 +17,7 @@ static const uint32_t PERIOD_HISTORY_FETCH_MAX = 64; class RGWOp_Period_Base : public RGWRESTOp { protected: RGWPeriod period; + std::ostringstream error_stream; public: int verify_permission() override { return 0; } void send_response() override; @@ -25,12 +26,19 @@ class RGWOp_Period_Base : public RGWRESTOp { // reply with the period object on success void RGWOp_Period_Base::send_response() { + s->err.message = error_stream.str(); + set_req_state_err(s, http_ret); dump_errno(s); end_header(s); - if (http_ret < 0) + if (http_ret < 0) { + if (!s->err.message.empty()) { + ldout(s->cct, 4) << "Request failed with " << http_ret + << ": " << s->err.message << dendl; + } return; + } encode_json("period", period, s->formatter); flusher.flush(); @@ -85,8 +93,8 @@ void RGWOp_Period_Post::execute() // require period.realm_id to match our realm if (period.get_realm() != store->realm.get_id()) { - lderr(cct) << "period with realm id " << period.get_realm() - << " doesn't match current realm " << store->realm.get_id() << dendl; + error_stream << "period with realm id " << period.get_realm() + << " doesn't match current realm " << store->realm.get_id() << std::endl; http_ret = -EINVAL; return; } @@ -112,7 +120,7 @@ void RGWOp_Period_Post::execute() // if period id is empty, handle as 'period commit' if (period.get_id().empty()) { - http_ret = period.commit(realm, current_period); + http_ret = period.commit(realm, current_period, error_stream); if (http_ret < 0) { lderr(cct) << "master zone failed to commit period" << dendl; } -- 2.39.5