Skip to content

Commit 1b66bc5

Browse files
shreyanshjain7174soumyakoduri
authored andcommitted
RGW: Cloud Restore cli and its corresponding response for user.
* For first and repititive request 202 Accepted will be corresponding response code. * For CloudRestored status 200 OK will be corresponding response code. * For conflicting requests 409 Conflict corresponding response code. Also Fixed storage class update while listing objects. Earlier while restoring object temporarily list-objects (s3api) and radosgw-admin bucket list didn't have updated storage class. With this fixed it now has the cloudtier storage class. Signed-off-by: shreyanshjain7174 <[email protected]>
1 parent c49aa6a commit 1b66bc5

File tree

7 files changed

+230
-0
lines changed

7 files changed

+230
-0
lines changed

src/rgw/driver/rados/rgw_rados.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3213,6 +3213,30 @@ int RGWRados::Object::Write::_do_write_meta(uint64_t size, uint64_t accounted_si
32133213
op.setxattr(RGW_ATTR_STORAGE_CLASS, bl);
32143214
}
32153215

3216+
/* For temporary restored copies, storage-class returned
3217+
* in GET/list-objects should correspond to original
3218+
* cloudtier storage class. For GET its handled in its REST
3219+
* response by verifying RESTORE_TYPE in attrs. But the same
3220+
* cannot be done for list-objects response and hence this
3221+
* needs to be updated in bi entry itself.
3222+
*/
3223+
auto attr_iter = attrs.find(RGW_ATTR_RESTORE_TYPE);
3224+
if (attr_iter != attrs.end()) {
3225+
rgw::sal::RGWRestoreType rt;
3226+
bufferlist bl = attr_iter->second;
3227+
auto iter = bl.cbegin();
3228+
decode(rt, iter);
3229+
3230+
if (rt == rgw::sal::RGWRestoreType::Temporary) {
3231+
// temporary restore; set storage-class to cloudtier storage class
3232+
auto c_iter = attrs.find(RGW_ATTR_CLOUDTIER_STORAGE_CLASS);
3233+
3234+
if (c_iter != attrs.end()) {
3235+
storage_class = rgw_bl_str(c_iter->second);
3236+
}
3237+
}
3238+
}
3239+
32163240
if (!op.size())
32173241
return 0;
32183242

src/rgw/rgw_op.cc

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5246,6 +5246,73 @@ void RGWPutMetadataObject::execute(optional_yield y)
52465246
op_ret = s->object->set_obj_attrs(this, &attrs, &rmattrs, s->yield, rgw::sal::FLAG_LOG_OP);
52475247
}
52485248

5249+
int RGWRestoreObj::init_processing(optional_yield y)
5250+
{
5251+
int op_ret = get_params(y);
5252+
if (op_ret < 0) {
5253+
return op_ret;
5254+
}
5255+
5256+
return RGWOp::init_processing(y);
5257+
}
5258+
5259+
int RGWRestoreObj::verify_permission(optional_yield y)
5260+
{
5261+
if (!verify_bucket_permission(this, s, ARN(s->object->get_obj()),
5262+
rgw::IAM::s3RestoreObject)) {
5263+
return -EACCES;
5264+
}
5265+
5266+
return 0;
5267+
}
5268+
5269+
void RGWRestoreObj::pre_exec()
5270+
{
5271+
rgw_bucket_object_pre_exec(s);
5272+
}
5273+
5274+
void RGWRestoreObj::execute(optional_yield y)
5275+
{
5276+
if (!s->bucket_exists) {
5277+
op_ret = -ERR_NO_SUCH_BUCKET;
5278+
return;
5279+
}
5280+
5281+
s->object->set_atomic();
5282+
int op_ret = s->object->get_obj_attrs(y, this);
5283+
if (op_ret < 0) {
5284+
ldpp_dout(this, 1) << "failed to fetch get_obj_attrs op ret = " << op_ret << dendl;
5285+
return;
5286+
}
5287+
rgw::sal::Attrs attrs = s->object->get_attrs();
5288+
auto attr_iter = attrs.find(RGW_ATTR_MANIFEST);
5289+
if (attr_iter != attrs.end()) {
5290+
RGWObjManifest m;
5291+
decode(m, attr_iter->second);
5292+
RGWObjTier tier_config;
5293+
m.get_tier_config(&tier_config);
5294+
if (m.get_tier_type() == "cloud-s3") {
5295+
ldpp_dout(this, 20) << "execute: expiry days" << expiry_days <<dendl;
5296+
op_ret = handle_cloudtier_obj(s, this, driver, attrs, false, expiry_days, true, y);
5297+
if (op_ret < 0) {
5298+
ldpp_dout(this, 4) << "Cannot get cloud tiered object: " << *s->object
5299+
<<". Failing with " << op_ret << dendl;
5300+
if (op_ret == -ERR_INVALID_OBJECT_STATE) {
5301+
s->err.message = "This object was transitioned to cloud-s3";
5302+
}
5303+
}
5304+
} else {
5305+
ldpp_dout(this, 20) << "not cloud tier object erroring" << dendl;
5306+
op_ret = -ERR_INVALID_OBJECT_STATE;
5307+
}
5308+
} else {
5309+
ldpp_dout(this, 20) << " manifest not found" << dendl;
5310+
}
5311+
ldpp_dout(this, 20) << "completed restore" << dendl;
5312+
5313+
return;
5314+
}
5315+
52495316
int RGWDeleteObj::handle_slo_manifest(bufferlist& bl, optional_yield y)
52505317
{
52515318
RGWSLOInfo slo_info;

src/rgw/rgw_op.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,24 @@ class RGWPutMetadataObject : public RGWOp {
14611461
virtual bool need_object_expiration() { return false; }
14621462
};
14631463

1464+
class RGWRestoreObj : public RGWOp {
1465+
protected:
1466+
std::optional<uint64_t> expiry_days;
1467+
public:
1468+
RGWRestoreObj() {}
1469+
1470+
int init_processing(optional_yield y) override;
1471+
int verify_permission(optional_yield y) override;
1472+
void pre_exec() override;
1473+
void execute(optional_yield y) override;
1474+
virtual int get_params(optional_yield y) {return 0;}
1475+
1476+
void send_response() override = 0;
1477+
const char* name() const override { return "restore_obj"; }
1478+
RGWOpType get_type() override { return RGW_OP_RESTORE_OBJ; }
1479+
uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1480+
};
1481+
14641482
class RGWDeleteObj : public RGWOp {
14651483
protected:
14661484
bool delete_marker;

src/rgw/rgw_op_type.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ enum RGWOpType {
2525
RGW_OP_PUT_METADATA_BUCKET,
2626
RGW_OP_PUT_METADATA_OBJECT,
2727
RGW_OP_SET_TEMPURL,
28+
RGW_OP_RESTORE_OBJ,
2829
RGW_OP_DELETE_OBJ,
2930
RGW_OP_COPY_OBJ,
3031
RGW_OP_GET_ACLS,

src/rgw/rgw_rest.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,12 @@ class RGWPutMetadataObject_ObjStore : public RGWPutMetadataObject
318318
~RGWPutMetadataObject_ObjStore() override {}
319319
};
320320

321+
class RGWRestoreObj_ObjStore : public RGWRestoreObj {
322+
public:
323+
RGWRestoreObj_ObjStore() {}
324+
~RGWRestoreObj_ObjStore() override {}
325+
};
326+
321327
class RGWDeleteObj_ObjStore : public RGWDeleteObj {
322328
public:
323329
RGWDeleteObj_ObjStore() {}

src/rgw/rgw_rest_s3.cc

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,6 +3451,106 @@ int RGWPostObj_ObjStore_S3::get_encrypt_filter(
34513451
return res;
34523452
}
34533453

3454+
struct RestoreObjectRequest {
3455+
std::optional<uint64_t> days;
3456+
3457+
void decode_xml(XMLObj *obj) {
3458+
RGWXMLDecoder::decode_xml("Days", days, obj);
3459+
}
3460+
3461+
void dump_xml(Formatter *f) const {
3462+
encode_xml("Days", days, f);
3463+
}
3464+
};
3465+
3466+
int RGWRestoreObj_ObjStore_S3::get_params(optional_yield y)
3467+
{
3468+
std::string expected_bucket_owner;
3469+
3470+
if (s->info.env->get("x-amz-expected-bucket-owner") != nullptr) {
3471+
expected_bucket_owner = s->info.env->get("x-amz-expected-bucket-owner");
3472+
}
3473+
3474+
const auto max_size = s->cct->_conf->rgw_max_put_param_size;
3475+
3476+
RGWXMLDecoder::XMLParser parser;
3477+
int r = 0;
3478+
bufferlist data;
3479+
std::tie(r, data) = read_all_input(s, max_size, false);
3480+
3481+
if (r < 0) {
3482+
return r;
3483+
}
3484+
3485+
if(!parser.init()) {
3486+
return -EINVAL;
3487+
}
3488+
3489+
if (!parser.parse(data.c_str(), data.length(), 1)) {
3490+
return -ERR_MALFORMED_XML;
3491+
}
3492+
3493+
RestoreObjectRequest request;
3494+
3495+
try {
3496+
RGWXMLDecoder::decode_xml("RestoreRequest", request, &parser);
3497+
}
3498+
catch (RGWXMLDecoder::err &err) {
3499+
ldpp_dout(this, 5) << "Malformed restore request: " << err << dendl;
3500+
return -EINVAL;
3501+
}
3502+
3503+
if (request.days) {
3504+
expiry_days = request.days.value();
3505+
ldpp_dout(this, 10) << "expiry_days=" << expiry_days << dendl;
3506+
} else {
3507+
expiry_days=nullopt;
3508+
ldpp_dout(this, 10) << "expiry_days=" << expiry_days << dendl;
3509+
}
3510+
3511+
return 0;
3512+
}
3513+
3514+
void RGWRestoreObj_ObjStore_S3::send_response()
3515+
{
3516+
if (op_ret < 0)
3517+
{
3518+
set_req_state_err(s, op_ret);
3519+
dump_errno(s);
3520+
end_header(s, this);
3521+
dump_start(s);
3522+
return;
3523+
}
3524+
3525+
rgw::sal::Attrs attrs = s->object->get_attrs();
3526+
auto attr_iter = attrs.find(RGW_ATTR_RESTORE_STATUS);
3527+
rgw::sal::RGWRestoreStatus restore_status;
3528+
if (attr_iter != attrs.end()) {
3529+
bufferlist bl = attr_iter->second;
3530+
auto iter = bl.cbegin();
3531+
decode(restore_status, iter);
3532+
}
3533+
ldpp_dout(this, 10) << "restore_status=" << restore_status << dendl;
3534+
3535+
if (attr_iter == attrs.end() || restore_status != rgw::sal::RGWRestoreStatus::None) {
3536+
s->err.http_ret = 202; //Accepted
3537+
dump_header(s, "x-amz-restore", rgw_bl_str(restore_status));
3538+
} else if (restore_status != rgw::sal::RGWRestoreStatus::RestoreAlreadyInProgress) {
3539+
s->err.http_ret = 409; // Conflict
3540+
dump_header_if_nonempty(s, "x-amz-restore", rgw_bl_str(restore_status));
3541+
} else if (restore_status != rgw::sal::RGWRestoreStatus::CloudRestored) {
3542+
s->err.http_ret = 200; // OK
3543+
dump_header_if_nonempty(s, "x-amz-restore", rgw_bl_str(restore_status));
3544+
} else {
3545+
s->err.http_ret = 202; // Accepted
3546+
dump_header_if_nonempty(s, "x-amz-restore", rgw_bl_str(restore_status));
3547+
}
3548+
3549+
dump_errno(s);
3550+
end_header(s, this);
3551+
dump_start(s);
3552+
}
3553+
34543554
int RGWDeleteObj_ObjStore_S3::get_params(optional_yield y)
34553555
{
34563556
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()
49105010
if (s->info.args.exists("uploads"))
49115011
return new RGWInitMultipart_ObjStore_S3;
49125012

5013+
if (s->info.args.exists("restore"))
5014+
return new RGWRestoreObj_ObjStore_S3;
5015+
49135016
if (is_select_op())
49145017
return rgw::s3select::create_s3select_op();
49155018

@@ -5961,6 +6064,7 @@ AWSGeneralAbstractor::get_auth_data_v4(const req_state* const s,
59616064
case RGW_OP_PUT_BUCKET_TAGGING:
59626065
case RGW_OP_PUT_BUCKET_REPLICATION:
59636066
case RGW_OP_PUT_LC:
6067+
case RGW_OP_RESTORE_OBJ:
59646068
case RGW_OP_SET_REQUEST_PAYMENT:
59656069
case RGW_OP_PUBSUB_NOTIF_CREATE:
59666070
case RGW_OP_PUBSUB_NOTIF_DELETE:

src/rgw/rgw_rest_s3.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,16 @@ class RGWPostObj_ObjStore_S3 : public RGWPostObj_ObjStore {
327327
rgw::sal::DataProcessor *cb) override;
328328
};
329329

330+
class RGWRestoreObj_ObjStore_S3 : public RGWRestoreObj_ObjStore {
331+
332+
public:
333+
RGWRestoreObj_ObjStore_S3() {}
334+
~RGWRestoreObj_ObjStore_S3() override {}
335+
336+
int get_params(optional_yield y) override;
337+
void send_response() override;
338+
};
339+
330340
class RGWDeleteObj_ObjStore_S3 : public RGWDeleteObj_ObjStore {
331341
public:
332342
RGWDeleteObj_ObjStore_S3() {}

0 commit comments

Comments
 (0)