rgw: rework lifecycle parsing

Use new style xml parsing, instead of inheriting from XMLParser.

Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
This commit is contained in:
Yehuda Sadeh 2018-11-01 17:54:42 -07:00
parent 408f04ff4a
commit dc808953f2
10 changed files with 328 additions and 589 deletions

View File

@ -30,6 +30,9 @@ namespace ceph {
ObjectSection(Formatter& f, const char *name) : formatter(f) {
formatter.open_object_section(name);
}
ObjectSection(Formatter& f, const char *name, const char *ns) : formatter(f) {
formatter.open_object_section_in_ns(name, ns);
}
~ObjectSection() {
formatter.close_section();
}
@ -41,6 +44,9 @@ namespace ceph {
ArraySection(Formatter& f, const char *name) : formatter(f) {
formatter.open_array_section(name);
}
ArraySection(Formatter& f, const char *name, const char *ns) : formatter(f) {
formatter.open_array_section_in_ns(name, ns);
}
~ArraySection() {
formatter.close_section();
}

View File

@ -36,7 +36,7 @@ typedef enum {
lc_processing,
lc_failed,
lc_complete,
}LC_BUCKET_STATUS;
} LC_BUCKET_STATUS;
class LCExpiration
{
@ -46,7 +46,7 @@ protected:
string date;
public:
LCExpiration() {}
~LCExpiration() {}
LCExpiration(const string& _days, const string& _date) : days(_days), date(_date) {}
void encode(bufferlist& bl) const {
ENCODE_START(3, 2, bl);
@ -92,7 +92,7 @@ public:
return true;
}
};
WRITE_CLASS_ENCODER(LCExpiration);
WRITE_CLASS_ENCODER(LCExpiration)
class LCTransition
{
@ -153,7 +153,7 @@ public:
}
void dump(Formatter *f) const;
};
WRITE_CLASS_ENCODER(LCTransition);
WRITE_CLASS_ENCODER(LCTransition)
class LCFilter
{
@ -209,7 +209,7 @@ class LCFilter
}
void dump(Formatter *f) const;
};
WRITE_CLASS_ENCODER(LCFilter);
WRITE_CLASS_ENCODER(LCFilter)

View File

@ -27,77 +27,100 @@ static bool check_date(const string& _date)
return true;
}
bool LCExpiration_S3::xml_end(const char * el) {
LCDays_S3 *lc_days = static_cast<LCDays_S3 *>(find_first("Days"));
LCDeleteMarker_S3 *lc_dm = static_cast<LCDeleteMarker_S3 *>(find_first("ExpiredObjectDeleteMarker"));
LCDate_S3 *lc_date = static_cast<LCDate_S3 *>(find_first("Date"));
if ((!lc_days && !lc_dm && !lc_date) || (lc_days && lc_dm)
|| (lc_days && lc_date) || (lc_dm && lc_date)) {
return false;
}
if (lc_days) {
days = lc_days->get_data();
} else if (lc_dm) {
dm_expiration = lc_dm->get_data().compare("true") == 0;
if (!dm_expiration) {
return false;
}
void LCExpiration_S3::dump_xml(Formatter *f) const {
if (dm_expiration) {
encode_xml("ExpiredObjectDeleteMarker", "true", f);
} else if (!days.empty()) {
encode_xml("Days", days, f);
} else {
date = lc_date->get_data();
encode_xml("Date", date, f);
}
}
void LCExpiration_S3::decode_xml(XMLObj *obj)
{
bool has_days = RGWXMLDecoder::decode_xml("Days", days, obj);
bool has_date = RGWXMLDecoder::decode_xml("Date", date, obj);
string dm;
bool has_dm = RGWXMLDecoder::decode_xml("ExpiredObjectDeleteMarker", dm, obj);
if ((!has_days && !has_dm && !has_date) || (has_days && has_dm)
|| (has_days && has_date) || (has_dm && has_date)) {
throw RGWXMLDecoder::err("bad Expiration section");
}
if (has_date && !check_date(date)) {
//We need return xml error according to S3
if (!check_date(date)) {
return false;
}
throw RGWXMLDecoder::err("bad date in Date section");
}
return true;
}
bool LCNoncurExpiration_S3::xml_end(const char *el) {
LCDays_S3 *lc_noncur_days = static_cast<LCDays_S3 *>(find_first("NoncurrentDays"));
if (!lc_noncur_days) {
return false;
}
days = lc_noncur_days->get_data();
return true;
void LCNoncurExpiration_S3::decode_xml(XMLObj *obj)
{
RGWXMLDecoder::decode_xml("NoncurrentDays", days, obj, true);
}
bool LCMPExpiration_S3::xml_end(const char *el) {
LCDays_S3 *lc_mp_days = static_cast<LCDays_S3 *>(find_first("DaysAfterInitiation"));
if (!lc_mp_days) {
return false;
}
days = lc_mp_days->get_data();
return true;
void LCNoncurExpiration_S3::dump_xml(Formatter *f) const
{
encode_xml("NoncurrentDays", days, f);
}
bool RGWLifecycleConfiguration_S3::xml_end(const char *el) {
XMLObjIter iter = find("Rule");
LCRule_S3 *rule = static_cast<LCRule_S3 *>(iter.get_next());
if (!rule)
return false;
while (rule) {
add_rule(rule);
rule = static_cast<LCRule_S3 *>(iter.get_next());
void LCMPExpiration_S3::decode_xml(XMLObj *obj)
{
RGWXMLDecoder::decode_xml("DaysAfterInitiation", days, obj, true);
}
void LCMPExpiration_S3::dump_xml(Formatter *f) const
{
encode_xml("DaysAfterInitiation", days, f);
}
void RGWLifecycleConfiguration_S3::decode_xml(XMLObj *obj)
{
vector<LCRule_S3> rules;
RGWXMLDecoder::decode_xml("Rule", rules, obj, true);
for (auto& rule : rules) {
add_rule(&rule);
}
if (cct->_conf->rgw_lc_max_rules < rule_map.size()) {
ldout(cct, 5) << "Warn: The lifecycle config has too many rules, rule number is:"
<< rule_map.size() << ", max number is:" << cct->_conf->rgw_lc_max_rules << dendl;
return false;
stringstream ss;
ss << "Warn: The lifecycle config has too many rules, rule number is:"
<< rule_map.size() << ", max number is:" << cct->_conf->rgw_lc_max_rules;
throw RGWXMLDecoder::err(ss.str());
}
return true;
}
bool LCFilter_S3::xml_end(const char* el) {
void LCFilter_S3::dump_xml(Formatter *f) const
{
if (has_prefix()) {
encode_xml("Prefix", prefix, f);
}
bool multi = has_multi_condition();
if (multi) {
f->open_array_section("And");
}
if (has_tags()) {
const auto& tagset_s3 = static_cast<const RGWObjTagSet_S3 &>(obj_tags);
tagset_s3.dump_xml(f);
}
if (multi) {
f->close_section();
}
}
XMLObj *o = find_first("And");
void LCFilter_S3::decode_xml(XMLObj *obj)
{
XMLObj *o = obj->find_first("And");
bool single_cond = false;
int num_conditions = 0;
// If there is an AND condition, every tag is a child of and
// else we only support single conditions and return false if we see multiple
if (o == nullptr){
o = this;
o = obj;
single_cond = true;
}
@ -114,65 +137,56 @@ bool LCFilter_S3::xml_end(const char* el) {
num_conditions++;
}
return !(single_cond && num_conditions > 1);
if (single_cond && num_conditions > 1) {
throw RGWXMLDecoder::err("Bad filter: badly formed multiple conditions");
}
}
bool LCTransition_S3::xml_end(const char* el) {
LCDays_S3 *lc_days = static_cast<LCDays_S3 *>(find_first("Days"));
LCDate_S3 *lc_date = static_cast<LCDate_S3 *>(find_first("Date"));
if ((lc_days && lc_date) || (!lc_days && !lc_date)) {
return false;
void LCTransition_S3::decode_xml(XMLObj *obj)
{
bool has_days = RGWXMLDecoder::decode_xml("Days", days, obj);
bool has_date = RGWXMLDecoder::decode_xml("Date", date, obj);
if ((has_days && has_date) || (!has_days && !has_date)) {
throw RGWXMLDecoder::err("bad Transition section");
}
if (lc_days) {
days = lc_days->get_data();
} else {
date = lc_date->get_data();
if (has_date && !check_date(date)) {
//We need return xml error according to S3
if (!check_date(date)) {
return false;
}
throw RGWXMLDecoder::err("bad Date in Transition section");
}
LCStorageClass_S3 *lc_storage_class = static_cast<LCStorageClass_S3 *>(find_first("StorageClass"));
if (!lc_storage_class) {
return false;
if (!RGWXMLDecoder::decode_xml("StorageClass", storage_class, obj)) {
throw RGWXMLDecoder::err("missing StorageClass in Transition section");
}
storage_class = lc_storage_class->get_data();
if (storage_class.compare("STANDARD_IA") != 0 && storage_class.compare("ONEZONE_IA") != 0 &&
storage_class.compare("GLACIER") != 0) {
return false;
}
return true;
}
bool LCNoncurTransition_S3::xml_end(const char* el) {
LCDays_S3 *lc_noncur_days = static_cast<LCDays_S3 *>(find_first("NoncurrentDays"));
if (!lc_noncur_days) {
return false;
void LCTransition_S3::dump_xml(Formatter *f) const {
if (!days.empty()) {
encode_xml("Days", days, f);
} else {
encode_xml("Date", date, f);
}
days = lc_noncur_days->get_data();
LCStorageClass_S3 *lc_storage_class = static_cast<LCStorageClass_S3 *>(find_first("StorageClass"));
if (!lc_storage_class) {
return false;
}
storage_class = lc_storage_class->get_data();
if (storage_class.compare("STANDARD_IA") != 0 && storage_class.compare("ONEZONE_IA") != 0 &&
storage_class.compare("GLACIER") != 0) {
return false;
}
return true;
encode_xml("StorageClass", storage_class, f);
}
void LCNoncurTransition_S3::decode_xml(XMLObj *obj)
{
if (!RGWXMLDecoder::decode_xml("NoncurrentDays", days, obj)) {
throw RGWXMLDecoder::err("missing NoncurrentDays in NoncurrentVersionTransition section");
}
if (!RGWXMLDecoder::decode_xml("StorageClass", storage_class, obj)) {
throw RGWXMLDecoder::err("missing StorageClass in NoncurrentVersionTransition section");
}
}
bool LCRule_S3::xml_end(const char *el) {
LCID_S3 *lc_id;
LCPrefix_S3 *lc_prefix;
LCStatus_S3 *lc_status;
LCExpiration_S3 *lc_expiration;
LCNoncurExpiration_S3 *lc_noncur_expiration;
LCMPExpiration_S3 *lc_mp_expiration;
LCFilter_S3 *lc_filter;
LCTransition_S3 *lc_transition;
LCNoncurTransition_S3 *lc_noncur_transition;
void LCNoncurTransition_S3::dump_xml(Formatter *f) const
{
encode_xml("NoncurrentDays", days, f);
encode_xml("StorageClass", storage_class, f);
}
void LCRule_S3::decode_xml(XMLObj *obj)
{
id.clear();
prefix.clear();
status.clear();
@ -181,19 +195,12 @@ bool LCRule_S3::xml_end(const char *el) {
// S3 generates a 48 bit random ID, maybe we could generate shorter IDs
static constexpr auto LC_ID_LENGTH = 48;
lc_id = static_cast<LCID_S3 *>(find_first("ID"));
if (lc_id){
id = lc_id->get_data();
} else {
if (!RGWXMLDecoder::decode_xml("ID", id, obj)) {
gen_rand_alphanumeric_lower(cct, &id, LC_ID_LENGTH);
}
lc_filter = static_cast<LCFilter_S3 *>(find_first("Filter"));
if (lc_filter){
filter = *lc_filter;
} else {
LCFilter_S3 filter_s3;
if (!RGWXMLDecoder::decode_xml("Filter", filter_s3, obj)) {
// Ideally the following code should be deprecated and we should return
// False here, The new S3 LC configuration xml spec. makes Filter mandatory
// and Prefix optional. However older clients including boto2 still generate
@ -202,101 +209,103 @@ bool LCRule_S3::xml_end(const char *el) {
// argument. A day will come when S3 enforces their own xml-spec, but it is
// not this day
lc_prefix = static_cast<LCPrefix_S3 *>(find_first("Prefix"));
if (!lc_prefix){
return false;
if (!RGWXMLDecoder::decode_xml("Prefix", prefix, obj)) {
throw RGWXMLDecoder::err("missing Prefix in Filter");
}
}
filter = (LCFilter)filter_s3;
prefix = lc_prefix->get_data();
if (!RGWXMLDecoder::decode_xml("Status", status, obj)) {
throw RGWXMLDecoder::err("missing Status in Filter");
}
if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0) {
throw RGWXMLDecoder::err("bad Status in Filter");
}
lc_status = static_cast<LCStatus_S3 *>(find_first("Status"));
if (!lc_status)
return false;
status = lc_status->get_data();
if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0)
return false;
LCExpiration_S3 s3_expiration;
LCExpiration_S3 s3_noncur_expiration;
LCExpiration_S3 s3_mp_expiration;
LCFilter_S3 s3_filter;
lc_expiration = static_cast<LCExpiration_S3 *>(find_first("Expiration"));
lc_noncur_expiration = static_cast<LCNoncurExpiration_S3 *>(find_first("NoncurrentVersionExpiration"));
lc_mp_expiration = static_cast<LCMPExpiration_S3 *>(find_first("AbortIncompleteMultipartUpload"));
bool has_expiration = RGWXMLDecoder::decode_xml("Expiration", s3_expiration, obj);
bool has_noncur_expiration = RGWXMLDecoder::decode_xml("NoncurrentVersionExpiration", s3_noncur_expiration, obj);
bool has_mp_expiration = RGWXMLDecoder::decode_xml("AbortIncompleteMultipartUpload", s3_mp_expiration, obj);
XMLObjIter iter = find("Transition");
lc_transition = static_cast<LCTransition_S3 *>(iter.get_next());
XMLObjIter noncur_iter = find("NoncurrentVersionTransition");
lc_noncur_transition = static_cast<LCNoncurTransition_S3 *>(noncur_iter.get_next());
vector<LCTransition_S3> transitions;
vector<LCNoncurTransition_S3> noncur_transitions;
if (!lc_expiration && !lc_noncur_expiration && !lc_mp_expiration && !lc_transition && !lc_noncur_transition) {
return false;
} else {
if (lc_expiration) {
if (lc_expiration->has_days()) {
expiration.set_days(lc_expiration->get_days_str());
} else if (lc_expiration->has_date()) {
expiration.set_date(lc_expiration->get_date());
} else {
dm_expiration = lc_expiration->get_dm_expiration();
}
}
if (lc_noncur_expiration) {
noncur_expiration = *lc_noncur_expiration;
}
if (lc_mp_expiration) {
mp_expiration = *lc_mp_expiration;
}
while (lc_transition) {
if (!add_transition(lc_transition)) {
return false;
}
lc_transition = static_cast<LCTransition_S3 *>(iter.get_next());
}
while (lc_noncur_transition) {
if (!add_noncur_transition(lc_noncur_transition)) {
return false;
}
lc_noncur_transition = static_cast<LCNoncurTransition_S3 *>(noncur_iter.get_next());
bool has_transition = RGWXMLDecoder::decode_xml("Transition", transitions, obj);
bool has_noncur_transition = RGWXMLDecoder::decode_xml("NoncurrentVersionTransition", noncur_transitions, obj);
if (!has_expiration &&
!has_noncur_expiration &&
!has_mp_expiration &&
!has_transition &&
!has_noncur_transition) {
throw RGWXMLDecoder::err("bad Rule");
}
if (has_expiration) {
if (s3_expiration.has_days() ||
s3_expiration.has_date()) {
expiration = s3_expiration;
} else {
dm_expiration = s3_expiration.get_dm_expiration();
}
}
if (has_noncur_expiration) {
noncur_expiration = s3_noncur_expiration;
}
if (has_mp_expiration) {
mp_expiration = s3_mp_expiration;
}
for (auto& t : transitions) {
if (!add_transition(&t)) {
throw RGWXMLDecoder::err("Failed to add transition");
}
}
for (auto& t : noncur_transitions) {
if (!add_noncur_transition(&t)) {
throw RGWXMLDecoder::err("Failed to add non-current version transition");
}
}
return true;
}
void LCRule_S3::to_xml(ostream& out) {
out << "<Rule>" ;
out << "<ID>" << id << "</ID>";
void LCRule_S3::dump_xml(Formatter *f) const {
encode_xml("ID", id, f);
// In case of an empty filter and an empty Prefix, we defer to Prefix.
if (!filter.empty()) {
LCFilter_S3& lc_filter = static_cast<LCFilter_S3&>(filter);
lc_filter.to_xml(out);
const LCFilter_S3& lc_filter = static_cast<const LCFilter_S3&>(filter);
encode_xml("Filter", lc_filter, f);
} else {
out << "<Prefix>" << prefix << "</Prefix>";
encode_xml("Prefix", prefix, f);
}
out << "<Status>" << status << "</Status>";
encode_xml("Status", status, f);
if (!expiration.empty() || dm_expiration) {
LCExpiration_S3 expir(expiration.get_days_str(), expiration.get_date(), dm_expiration);
expir.to_xml(out);
encode_xml("Expiration", expir, f);
}
if (!noncur_expiration.empty()) {
LCNoncurExpiration_S3& noncur_expir = static_cast<LCNoncurExpiration_S3&>(noncur_expiration);
noncur_expir.to_xml(out);
const LCNoncurExpiration_S3& noncur_expir = static_cast<const LCNoncurExpiration_S3&>(noncur_expiration);
encode_xml("NoncurrentVersionExpiration", noncur_expir, f);
}
if (!mp_expiration.empty()) {
LCMPExpiration_S3& mp_expir = static_cast<LCMPExpiration_S3&>(mp_expiration);
mp_expir.to_xml(out);
const LCMPExpiration_S3& mp_expir = static_cast<const LCMPExpiration_S3&>(mp_expiration);
encode_xml("AbortIncompleteMultipartUpload", mp_expir, f);
}
if (!transitions.empty()) {
for (auto &elem : transitions) {
LCTransition_S3& tran = static_cast<LCTransition_S3&>(elem.second);
tran.to_xml(out);
const LCTransition_S3& tran = static_cast<const LCTransition_S3&>(elem.second);
encode_xml("Transition", tran, f);
}
}
if (!noncur_transitions.empty()) {
for (auto &elem : noncur_transitions) {
LCNoncurTransition_S3& noncur_tran = static_cast<LCNoncurTransition_S3&>(elem.second);
noncur_tran.to_xml(out);
const LCNoncurTransition_S3& noncur_tran = static_cast<const LCNoncurTransition_S3&>(elem.second);
encode_xml("NoncurrentVersionTransition", noncur_tran, f);
}
}
out << "</Rule>";
}
int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfiguration& dest)
@ -316,58 +325,11 @@ int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfigura
}
void RGWLifecycleConfiguration_S3::dump_xml(Formatter *f) const
{
f->open_object_section_in_ns("LifecycleConfiguration", XMLNS_AWS_S3);
for (auto iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
const LCRule_S3& rule = static_cast<const LCRule_S3&>(iter->second);
rule.dump_xml(f);
}
f->close_section(); // Lifecycle
}
XMLObj *RGWLCXMLParser_S3::alloc_obj(const char *el)
{
XMLObj * obj = NULL;
if (strcmp(el, "LifecycleConfiguration") == 0) {
obj = new RGWLifecycleConfiguration_S3(cct);
} else if (strcmp(el, "Rule") == 0) {
obj = new LCRule_S3(cct);
} else if (strcmp(el, "ID") == 0) {
obj = new LCID_S3();
} else if (strcmp(el, "Prefix") == 0) {
obj = new LCPrefix_S3();
} else if (strcmp(el, "Filter") == 0) {
obj = new LCFilter_S3();
} else if (strcmp(el, "Status") == 0) {
obj = new LCStatus_S3();
} else if (strcmp(el, "Expiration") == 0) {
obj = new LCExpiration_S3();
} else if (strcmp(el, "Days") == 0) {
obj = new LCDays_S3();
} else if (strcmp(el, "Date") == 0) {
obj = new LCDate_S3();
} else if (strcmp(el, "ExpiredObjectDeleteMarker") == 0) {
obj = new LCDeleteMarker_S3();
} else if (strcmp(el, "NoncurrentVersionExpiration") == 0) {
obj = new LCNoncurExpiration_S3();
} else if (strcmp(el, "NoncurrentDays") == 0) {
obj = new LCDays_S3();
} else if (strcmp(el, "AbortIncompleteMultipartUpload") == 0) {
obj = new LCMPExpiration_S3();
} else if (strcmp(el, "DaysAfterInitiation") == 0) {
obj = new LCDays_S3();
} else if (strcmp(el, "StorageClass") == 0) {
obj = new LCStorageClass_S3();
} else if (strcmp(el, "Transition") == 0) {
obj = new LCTransition_S3();
} else if (strcmp(el, "NoncurrentVersionTransition") == 0) {
obj = new LCNoncurTransition_S3();
for (auto iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
const LCRule_S3& rule = static_cast<const LCRule_S3&>(iter->second);
encode_xml("Rule", rule, f);
}
return obj;
}

View File

@ -14,134 +14,23 @@
#include "rgw_xml.h"
#include "rgw_tag_s3.h"
class LCID_S3 : public XMLObj
class LCFilter_S3 : public LCFilter
{
public:
LCID_S3() {}
~LCID_S3() override {}
string& to_str() { return data; }
void dump_xml(Formatter *f) const;
void decode_xml(XMLObj *obj);
};
class LCPrefix_S3 : public XMLObj
{
public:
LCPrefix_S3() {}
~LCPrefix_S3() override {}
string& to_str() { return data; }
};
class LCFilter_S3 : public LCFilter, public XMLObj
{
public:
~LCFilter_S3() override {}
string& to_str() { return data; }
void to_xml(ostream& out){
out << "<Filter>";
stringstream ss;
if (has_prefix())
out << "<Prefix>" << prefix << "</Prefix>";
if (has_tags()){
for (const auto&kv : obj_tags.get_tags()){
ss << "<Tag>";
ss << "<Key>" << kv.first << "</Key>";
ss << "<Value>" << kv.second << "</Value>";
ss << "</Tag>";
}
}
if (has_multi_condition()) {
out << "<And>" << ss.str() << "</And>";
} else {
out << ss.str();
}
out << "</Filter>";
}
void dump_xml(Formatter *f) const {
f->open_object_section("Filter");
if (has_multi_condition())
f->open_object_section("And");
if (!prefix.empty())
encode_xml("Prefix", prefix, f);
if (has_tags()){
const auto& tagset_s3 = static_cast<const RGWObjTagSet_S3 &>(obj_tags);
tagset_s3.dump_xml(f);
}
if (has_multi_condition())
f->close_section(); // And;
f->close_section(); // Filter
}
bool xml_end(const char *el) override;
};
class LCStatus_S3 : public XMLObj
{
public:
LCStatus_S3() {}
~LCStatus_S3() override {}
string& to_str() { return data; }
};
class LCDays_S3 : public XMLObj
{
public:
LCDays_S3() {}
~LCDays_S3() override {}
string& to_str() { return data; }
};
class LCDate_S3 : public XMLObj
{
public:
LCDate_S3() {}
~LCDate_S3() override {}
string& to_str() { return data; }
};
class LCDeleteMarker_S3 : public XMLObj
{
public:
LCDeleteMarker_S3() {}
~LCDeleteMarker_S3() override {}
string& to_str() { return data; }
};
class LCExpiration_S3 : public LCExpiration, public XMLObj
class LCExpiration_S3 : public LCExpiration
{
private:
bool dm_expiration;
bool dm_expiration{false};
public:
LCExpiration_S3(): dm_expiration(false) {}
LCExpiration_S3(string _days, string _date, bool _dm_expiration) {
days = _days;
date = _date;
dm_expiration = _dm_expiration;
}
~LCExpiration_S3() override {}
LCExpiration_S3() {}
LCExpiration_S3(string _days, string _date, bool _dm_expiration) : LCExpiration(_days, _date), dm_expiration(_dm_expiration) {}
bool xml_end(const char *el) override;
void to_xml(ostream& out) {
out << "<Expiration>";
if (dm_expiration) {
out << "<ExpiredObjectDeleteMarker>" << "true" << "</ExpiredObjectDeleteMarker>";
} else if (!days.empty()){
out << "<Days>" << days << "</Days>";
} else {
out << "<Date>" << date << "</Date>";
}
out << "</Expiration>";
}
void dump_xml(Formatter *f) const {
f->open_object_section("Expiration");
if (dm_expiration) {
encode_xml("ExpiredObjectDeleteMarker", "true", f);
} else if (!days.empty()) {
encode_xml("Days", days, f);
} else {
encode_xml("Date", date, f);
}
f->close_section(); // Expiration
}
void dump_xml(Formatter *f) const;
void decode_xml(XMLObj *obj);
void set_dm_expiration(bool _dm_expiration) {
dm_expiration = _dm_expiration;
@ -152,180 +41,67 @@ public:
}
};
class LCNoncurExpiration_S3 : public LCExpiration, public XMLObj
class LCNoncurExpiration_S3 : public LCExpiration
{
public:
LCNoncurExpiration_S3() {}
~LCNoncurExpiration_S3() override {}
bool xml_end(const char *el) override;
void to_xml(ostream& out) {
out << "<NoncurrentVersionExpiration>" << "<NoncurrentDays>" << days << "</NoncurrentDays>"<< "</NoncurrentVersionExpiration>";
}
void dump_xml(Formatter *f) const {
f->open_object_section("NoncurrentVersionExpiration");
encode_xml("NoncurrentDays", days, f);
f->close_section();
}
void decode_xml(XMLObj *obj);
void dump_xml(Formatter *f) const;
};
class LCMPExpiration_S3 : public LCExpiration, public XMLObj
class LCMPExpiration_S3 : public LCExpiration
{
public:
LCMPExpiration_S3() {}
~LCMPExpiration_S3() {}
bool xml_end(const char *el) override;
void to_xml(ostream& out) {
out << "<AbortIncompleteMultipartUpload>" << "<DaysAfterInitiation>" << days << "</DaysAfterInitiation>" << "</AbortIncompleteMultipartUpload>";
}
void dump_xml(Formatter *f) const {
f->open_object_section("AbortIncompleteMultipartUpload");
encode_xml("DaysAfterInitiation", days, f);
f->close_section();
}
void decode_xml(XMLObj *obj);
void dump_xml(Formatter *f) const;
};
class LCStorageClass_S3 : public XMLObj
{
public:
LCStorageClass_S3() {}
~LCStorageClass_S3() override {}
string& to_str() { return data; }
};
class LCTransition_S3 : public LCTransition, public XMLObj
class LCTransition_S3 : public LCTransition
{
public:
LCTransition_S3() {}
~LCTransition_S3() {}
bool xml_end(const char *el) override;
void to_xml(ostream& out) {
out << "<Transition>";
if (!days.empty()) {
out << "<Days>" << days << "</Days>";
} else {
out << "<Date>" << date << "</Date>";
}
out << "<StorageClass>" << storage_class << "</StorageClass>" << "</Transition>";
}
void dump_xml(Formatter *f) const {
f->open_object_section("Transition");
if (!days.empty()) {
encode_xml("Days", days, f);
} else {
encode_xml("Date", date, f);
}
encode_xml("StorageClass", storage_class, f);
f->close_section();
}
void decode_xml(XMLObj *obj);
void dump_xml(Formatter *f) const;
};
class LCNoncurTransition_S3 : public LCTransition, public XMLObj
class LCNoncurTransition_S3 : public LCTransition
{
public:
LCNoncurTransition_S3() {}
~LCNoncurTransition_S3() {}
bool xml_end(const char *el) override;
void to_xml(ostream& out) {
out << "<NoncurrentVersionTransition>" << "<NoncurrentDays>" << days << "</NoncurrentDays>"
<< "<StorageClass>" << storage_class << "</StorageClass>" << "</NoncurrentVersionTransition>";
}
void dump_xml(Formatter *f) const {
f->open_object_section("NoncurrentVersionTransition");
encode_xml("NoncurrentDays", days, f);
encode_xml("StorageClass", storage_class, f);
f->close_section();
}
void decode_xml(XMLObj *obj);
void dump_xml(Formatter *f) const;
};
class LCRule_S3 : public LCRule, public XMLObj
class LCRule_S3 : public LCRule
{
private:
CephContext *cct;
public:
LCRule_S3(): cct(nullptr) {}
explicit LCRule_S3(CephContext *_cct): cct(_cct) {}
~LCRule_S3() override {}
void to_xml(ostream& out);
bool xml_end(const char *el) override;
bool xml_start(const char *el, const char **attr);
void dump_xml(Formatter *f) const {
f->open_object_section("Rule");
encode_xml("ID", id, f);
// In case of an empty filter and an empty Prefix, we defer to Prefix.
if (!filter.empty()) {
const LCFilter_S3& lc_filter = static_cast<const LCFilter_S3&>(filter);
lc_filter.dump_xml(f);
} else {
encode_xml("Prefix", prefix, f);
}
encode_xml("Status", status, f);
if (!expiration.empty() || dm_expiration) {
LCExpiration_S3 expir(expiration.get_days_str(), expiration.get_date(), dm_expiration);
expir.dump_xml(f);
}
if (!noncur_expiration.empty()) {
const LCNoncurExpiration_S3& noncur_expir = static_cast<const LCNoncurExpiration_S3&>(noncur_expiration);
noncur_expir.dump_xml(f);
}
if (!mp_expiration.empty()) {
const LCMPExpiration_S3& mp_expir = static_cast<const LCMPExpiration_S3&>(mp_expiration);
mp_expir.dump_xml(f);
}
if (!transitions.empty()) {
for (auto &elem : transitions) {
const LCTransition_S3& tran = static_cast<const LCTransition_S3&>(elem.second);
tran.dump_xml(f);
}
}
if (!noncur_transitions.empty()) {
for (auto &elem : noncur_transitions) {
const LCNoncurTransition_S3& noncur_tran = static_cast<const LCNoncurTransition_S3&>(elem.second);
noncur_tran.dump_xml(f);
}
}
f->close_section(); // Rule
}
void dump_xml(Formatter *f) const;
void decode_xml(XMLObj *obj);
void set_ctx(CephContext *ctx) {
cct = ctx;
}
};
class RGWLCXMLParser_S3 : public RGWXMLParser
{
CephContext *cct;
XMLObj *alloc_obj(const char *el) override;
public:
explicit RGWLCXMLParser_S3(CephContext *_cct) : cct(_cct) {}
};
class RGWLifecycleConfiguration_S3 : public RGWLifecycleConfiguration, public XMLObj
class RGWLifecycleConfiguration_S3 : public RGWLifecycleConfiguration
{
public:
explicit RGWLifecycleConfiguration_S3(CephContext *_cct) : RGWLifecycleConfiguration(_cct) {}
RGWLifecycleConfiguration_S3() : RGWLifecycleConfiguration(NULL) {}
~RGWLifecycleConfiguration_S3() override {}
RGWLifecycleConfiguration_S3() : RGWLifecycleConfiguration(nullptr) {}
bool xml_end(const char *el) override;
void to_xml(ostream& out) {
out << "<LifecycleConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">";
multimap<string, LCRule>::iterator iter;
for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
LCRule_S3& rule = static_cast<LCRule_S3&>(iter->second);
rule.to_xml(out);
}
out << "</LifecycleConfiguration>";
}
void decode_xml(XMLObj *obj);
int rebuild(RGWRados *store, RGWLifecycleConfiguration& dest);
void dump_xml(Formatter *f) const;
};

View File

@ -5118,8 +5118,8 @@ void RGWPutLC::execute()
{
bufferlist bl;
RGWLifecycleConfiguration_S3 *config = NULL;
RGWLCXMLParser_S3 parser(s->cct);
RGWLifecycleConfiguration_S3 config;
RGWXMLParser parser;
RGWLifecycleConfiguration_S3 new_config(s->cct);
content_md5 = s->info.env->get("HTTP_CONTENT_MD5");
@ -5172,20 +5172,25 @@ void RGWPutLC::execute()
op_ret = -ERR_MALFORMED_XML;
return;
}
config = static_cast<RGWLifecycleConfiguration_S3 *>(parser.find_first("LifecycleConfiguration"));
if (!config) {
op_ret = -ERR_MALFORMED_XML;
try {
RGWXMLDecoder::decode_xml("LifecycleConfiguration", config, &parser);
} catch (RGWXMLDecoder::err& err) {
ldpp_dout(this, 5) << "Bad lifecycle configuration: " << err << dendl;
op_ret = -EINVAL;
return;
}
op_ret = config->rebuild(store, new_config);
op_ret = config.rebuild(store, new_config);
if (op_ret < 0)
return;
if (s->cct->_conf->subsys.should_gather<ceph_subsys_rgw, 15>()) {
ldpp_dout(this, 15) << "New LifecycleConfiguration:";
new_config.to_xml(*_dout);
*_dout << dendl;
XMLFormatter xf;
new_config.dump_xml(&xf);
stringstream ss;
xf.flush(ss);
ldpp_dout(this, 15) << "New LifecycleConfiguration:" << ss.str() << dendl;
}
op_ret = store->get_lc()->set_bucket_config(s->bucket_info, s->bucket_attrs, &new_config);

View File

@ -402,7 +402,7 @@ void RGWGetObjTags_ObjStore_S3::send_response_data(bufferlist& bl)
int RGWPutObjTags_ObjStore_S3::get_params()
{
RGWObjTagsXMLParser parser;
RGWXMLParser parser;
if (!parser.init()){
return -EINVAL;
@ -421,17 +421,17 @@ int RGWPutObjTags_ObjStore_S3::get_params()
return -ERR_MALFORMED_XML;
}
RGWObjTagSet_S3 *obj_tags_s3;
RGWObjTagging_S3 *tagging;
RGWObjTagging_S3 tagging;
tagging = static_cast<RGWObjTagging_S3 *>(parser.find_first("Tagging"));
obj_tags_s3 = static_cast<RGWObjTagSet_S3 *>(tagging->find_first("TagSet"));
if(!obj_tags_s3){
try {
RGWXMLDecoder::decode_xml("Tagging", tagging, &parser);
} catch (RGWXMLDecoder::err& err) {
ldout(s->cct, 5) << "Malformed tagging request: " << err << dendl;
return -ERR_MALFORMED_XML;
}
RGWObjTags obj_tags;
r = obj_tags_s3->rebuild(obj_tags);
r = tagging.rebuild(obj_tags);
if (r < 0)
return r;
@ -1758,7 +1758,7 @@ int RGWPostObj_ObjStore_S3::get_tags()
{
string tags_str;
if (part_str(parts, "tagging", &tags_str)) {
RGWObjTagsXMLParser parser;
RGWXMLParser parser;
if (!parser.init()){
ldout(s->cct, 0) << "Couldn't init RGWObjTags XML parser" << dendl;
err_msg = "Server couldn't process the request";
@ -1770,17 +1770,17 @@ int RGWPostObj_ObjStore_S3::get_tags()
return -EINVAL;
}
RGWObjTagSet_S3 *obj_tags_s3;
RGWObjTagging_S3 *tagging;
RGWObjTagging_S3 tagging;
tagging = static_cast<RGWObjTagging_S3 *>(parser.find_first("Tagging"));
obj_tags_s3 = static_cast<RGWObjTagSet_S3 *>(tagging->find_first("TagSet"));
if(!obj_tags_s3){
return -ERR_MALFORMED_XML;
try {
RGWXMLDecoder::decode_xml("Tagging", tagging, &parser);
} catch (RGWXMLDecoder::err& err) {
ldout(s->cct, 5) << "Malformed tagging request: " << err << dendl;
return -EINVAL;
}
RGWObjTags obj_tags;
int r = obj_tags_s3->rebuild(obj_tags);
int r = tagging.rebuild(obj_tags);
if (r < 0)
return r;

View File

@ -9,43 +9,41 @@
#include "rgw_tag_s3.h"
bool RGWObjTagEntry_S3::xml_end(const char*){
RGWObjTagKey_S3 *key_obj = static_cast<RGWObjTagKey_S3 *>(find_first("Key"));
RGWObjTagValue_S3 *val_obj = static_cast<RGWObjTagValue_S3 *>(find_first("Value"));
if (!key_obj)
return false;
string s = key_obj->get_data();
if (s.empty()){
return false;
}
key = s;
if (val_obj) {
val = val_obj->get_data();
}
return true;
void RGWObjTagEntry_S3::decode_xml(XMLObj *obj) {
RGWXMLDecoder::decode_xml("Key", key, obj, true);
RGWXMLDecoder::decode_xml("Value", val, obj, true);
}
bool RGWObjTagSet_S3::xml_end(const char*){
XMLObjIter iter = find("Tag");
RGWObjTagEntry_S3 *tagentry = static_cast<RGWObjTagEntry_S3 *>(iter.get_next());
while (tagentry) {
const std::string& key = tagentry->get_key();
const std::string& val = tagentry->get_val();
if (!add_tag(key,val))
return false;
void RGWObjTagEntry_S3::dump_xml(Formatter *f) const {
encode_xml("Key", key, f);
encode_xml("Value", val, f);
tagentry = static_cast<RGWObjTagEntry_S3 *>(iter.get_next());
if (key.empty()) {
throw RGWXMLDecoder::err("empty key");
}
if (val.empty()) {
throw RGWXMLDecoder::err("empty val");
}
return true;
}
int RGWObjTagSet_S3::rebuild(RGWObjTags& dest){
void RGWObjTagSet_S3::decode_xml(XMLObj *obj) {
vector<RGWObjTagEntry_S3> entries;
RGWXMLDecoder::decode_xml("Tag", entries, obj, true);
for (auto& entry : entries) {
const std::string& key = entry.get_key();
const std::string& val = entry.get_val();
if (!add_tag(key,val)) {
throw RGWXMLDecoder::err("failed to add tag");
}
}
}
int RGWObjTagSet_S3::rebuild(RGWObjTags& dest) {
int ret;
for (const auto &it: tag_map){
for (const auto &it : tag_map){
ret = dest.check_and_add_tag(it.first, it.second);
if (ret < 0)
return ret;
@ -53,34 +51,15 @@ int RGWObjTagSet_S3::rebuild(RGWObjTags& dest){
return 0;
}
bool RGWObjTagging_S3::xml_end(const char*){
RGWObjTagSet_S3 *tagset = static_cast<RGWObjTagSet_S3 *> (find_first("TagSet"));
return tagset != nullptr;
void RGWObjTagging_S3::decode_xml(XMLObj *obj) {
RGWXMLDecoder::decode_xml("TagSet", tagset, obj, true);
}
void RGWObjTagSet_S3::dump_xml(Formatter *f) const {
for (const auto& tag: tag_map){
f->open_object_section("Tag");
f->dump_string("Key", tag.first);
f->dump_string("Value", tag.second);
f->close_section();
for (const auto& tag : tag_map){
Formatter::ObjectSection os(*f, "Tag");
encode_xml("Key", tag.first, f);
encode_xml("Value", tag.second, f);
}
}
XMLObj *RGWObjTagsXMLParser::alloc_obj(const char *el){
XMLObj* obj = nullptr;
if(strcmp(el,"Tagging") == 0) {
obj = new RGWObjTagging_S3();
} else if (strcmp(el,"TagSet") == 0) {
obj = new RGWObjTagSet_S3();
} else if (strcmp(el,"Tag") == 0) {
obj = new RGWObjTagEntry_S3();
} else if (strcmp(el,"Key") == 0) {
obj = new RGWObjTagKey_S3();
} else if (strcmp(el,"Value") == 0) {
obj = new RGWObjTagValue_S3();
}
return obj;
}

View File

@ -14,15 +14,7 @@
#include "rgw_tag.h"
#include "rgw_xml.h"
struct RGWObjTagKey_S3: public XMLObj
{
};
struct RGWObjTagValue_S3: public XMLObj
{
};
class RGWObjTagEntry_S3: public XMLObj
class RGWObjTagEntry_S3
{
std::string key;
std::string val;
@ -31,32 +23,31 @@ public:
RGWObjTagEntry_S3(const std::string &k, const std::string &v):key(k),val(v) {};
~RGWObjTagEntry_S3() {}
bool xml_end(const char*) override;
const std::string& get_key () const { return key;}
const std::string& get_val () const { return val;}
//void to_xml(CephContext *cct, ostream& out) const;
};
const std::string& get_key () const { return key; }
const std::string& get_val () const { return val; }
class RGWObjTagSet_S3: public RGWObjTags, public XMLObj
{
public:
bool xml_end(const char*) override;
void dump_xml(Formatter *f) const;
void decode_xml(XMLObj *obj);
};
class RGWObjTagSet_S3: public RGWObjTags
{
public:
int rebuild(RGWObjTags& dest);
void dump_xml(Formatter *f) const;
void decode_xml(XMLObj *obj);
};
class RGWObjTagging_S3: public XMLObj
class RGWObjTagging_S3
{
RGWObjTagSet_S3 tagset;
public:
bool xml_end(const char*) override;
void decode_xml(XMLObj *obj);
int rebuild(RGWObjTags& dest) {
return tagset.rebuild(dest);
}
};
class RGWObjTagsXMLParser : public RGWXMLParser
{
XMLObj *alloc_obj(const char *el) override;
public:
RGWObjTagsXMLParser() {}
~RGWObjTagsXMLParser() {}
};
#endif /* RGW_TAG_S3_H */

View File

@ -120,6 +120,20 @@ find(string name)
return iter;
}
XMLObjIter XMLObj::find_first()
{
XMLObjIter iter;
map<string, XMLObj *>::iterator first;
map<string, XMLObj *>::iterator last;
first = children.begin();
if (first != children.end()) {
last = children.upper_bound(first->first);
}else
last = children.end();
iter.set(first, last);
return iter;
}
XMLObj *XMLObj::
find_first(string name)
{

View File

@ -51,6 +51,7 @@ public:
void add_child(string el, XMLObj *obj);
bool get_attr(string name, string& attr);
XMLObjIter find(string name);
XMLObjIter find_first();
XMLObj *find_first(string name);
friend ostream& operator<<(ostream &out, const XMLObj &obj);
@ -117,6 +118,11 @@ public:
static void decode_xml(const char *name, T& val, T& default_val, XMLObj *obj);
};
static inline ostream& operator<<(ostream &out, RGWXMLDecoder::err& err)
{
return out << err.message;
}
template<class T>
void decode_xml_obj(T& val, XMLObj *obj)
{
@ -155,17 +161,17 @@ void do_decode_xml_obj(list<T>& l, const string& name, XMLObj *obj)
}
template<class T>
void do_decode_xml_obj(vector<T>& l, const string& name, XMLObj *obj)
void decode_xml_obj(std::vector<T>& v, XMLObj *obj)
{
l.clear();
v.clear();
XMLObjIter iter = obj->find(name);
XMLObjIter iter = obj->find_first();
XMLObj *o;
while (o = iter.get_next()) {
while ((o = iter.get_next())) {
T val;
decode_xml_obj(val, o);
l.push_back(val);
v.push_back(val);
}
}