summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_rest_s3.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rgw/rgw_rest_s3.cc')
-rw-r--r--src/rgw/rgw_rest_s3.cc104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index 0289aca6773..6df57b39fea 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -3451,6 +3451,106 @@ int RGWPostObj_ObjStore_S3::get_encrypt_filter(
return res;
}
+struct RestoreObjectRequest {
+ std::optional<uint64_t> days;
+
+ void decode_xml(XMLObj *obj) {
+ RGWXMLDecoder::decode_xml("Days", days, obj);
+ }
+
+ void dump_xml(Formatter *f) const {
+ encode_xml("Days", days, f);
+ }
+};
+
+int RGWRestoreObj_ObjStore_S3::get_params(optional_yield y)
+{
+ std::string expected_bucket_owner;
+
+ if (s->info.env->get("x-amz-expected-bucket-owner") != nullptr) {
+ expected_bucket_owner = s->info.env->get("x-amz-expected-bucket-owner");
+ }
+
+ const auto max_size = s->cct->_conf->rgw_max_put_param_size;
+
+ RGWXMLDecoder::XMLParser parser;
+ int r = 0;
+ bufferlist data;
+ std::tie(r, data) = read_all_input(s, max_size, false);
+
+ if (r < 0) {
+ return r;
+ }
+
+ if(!parser.init()) {
+ return -EINVAL;
+ }
+
+ if (!parser.parse(data.c_str(), data.length(), 1)) {
+ return -ERR_MALFORMED_XML;
+ }
+
+ RestoreObjectRequest request;
+
+ try {
+ RGWXMLDecoder::decode_xml("RestoreRequest", request, &parser);
+ }
+ catch (RGWXMLDecoder::err &err) {
+ ldpp_dout(this, 5) << "Malformed restore request: " << err << dendl;
+ return -EINVAL;
+ }
+
+ if (request.days) {
+ expiry_days = request.days.value();
+ ldpp_dout(this, 10) << "expiry_days=" << expiry_days << dendl;
+ } else {
+ expiry_days=nullopt;
+ ldpp_dout(this, 10) << "expiry_days=" << expiry_days << dendl;
+ }
+
+ return 0;
+}
+
+void RGWRestoreObj_ObjStore_S3::send_response()
+{
+ if (op_ret < 0)
+ {
+ set_req_state_err(s, op_ret);
+ dump_errno(s);
+ end_header(s, this);
+ dump_start(s);
+ return;
+ }
+
+ rgw::sal::Attrs attrs = s->object->get_attrs();
+ auto attr_iter = attrs.find(RGW_ATTR_RESTORE_STATUS);
+ rgw::sal::RGWRestoreStatus restore_status;
+ if (attr_iter != attrs.end()) {
+ bufferlist bl = attr_iter->second;
+ auto iter = bl.cbegin();
+ decode(restore_status, iter);
+ }
+ ldpp_dout(this, 10) << "restore_status=" << restore_status << dendl;
+
+ if (attr_iter == attrs.end() || restore_status != rgw::sal::RGWRestoreStatus::None) {
+ s->err.http_ret = 202; //Accepted
+ dump_header(s, "x-amz-restore", rgw_bl_str(restore_status));
+ } else if (restore_status != rgw::sal::RGWRestoreStatus::RestoreAlreadyInProgress) {
+ s->err.http_ret = 409; // Conflict
+ dump_header_if_nonempty(s, "x-amz-restore", rgw_bl_str(restore_status));
+ } else if (restore_status != rgw::sal::RGWRestoreStatus::CloudRestored) {
+ s->err.http_ret = 200; // OK
+ dump_header_if_nonempty(s, "x-amz-restore", rgw_bl_str(restore_status));
+ } else {
+ s->err.http_ret = 202; // Accepted
+ dump_header_if_nonempty(s, "x-amz-restore", rgw_bl_str(restore_status));
+ }
+
+ dump_errno(s);
+ end_header(s, this);
+ dump_start(s);
+}
+
int RGWDeleteObj_ObjStore_S3::get_params(optional_yield y)
{
const char *if_unmod = s->info.env->get("HTTP_X_AMZ_DELETE_IF_UNMODIFIED_SINCE");
@@ -4910,6 +5010,9 @@ RGWOp *RGWHandler_REST_Obj_S3::op_post()
if (s->info.args.exists("uploads"))
return new RGWInitMultipart_ObjStore_S3;
+ if (s->info.args.exists("restore"))
+ return new RGWRestoreObj_ObjStore_S3;
+
if (is_select_op())
return rgw::s3select::create_s3select_op();
@@ -5961,6 +6064,7 @@ AWSGeneralAbstractor::get_auth_data_v4(const req_state* const s,
case RGW_OP_PUT_BUCKET_TAGGING:
case RGW_OP_PUT_BUCKET_REPLICATION:
case RGW_OP_PUT_LC:
+ case RGW_OP_RESTORE_OBJ:
case RGW_OP_SET_REQUEST_PAYMENT:
case RGW_OP_PUBSUB_NOTIF_CREATE:
case RGW_OP_PUBSUB_NOTIF_DELETE: