rgw: 'period commit' supplies user-readable error messages

Signed-off-by: Casey Bodley <cbodley@redhat.com>
This commit is contained in:
Casey Bodley 2016-03-21 14:51:58 -04:00
parent 292d8967d4
commit d951ee5f5b
4 changed files with 31 additions and 15 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -1469,7 +1469,8 @@ public:
int update();
// commit a staging period; only for use on master zone
int commit(RGWRealm& realm, const RGWPeriod &current_period);
int commit(RGWRealm& realm, const RGWPeriod &current_period,
std::ostream& error_stream);
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);

View File

@ -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;
}