]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add lifecycle validation according to S3.
authorZhang Shaowen <zhangshaowen@cmss.chinamobile.com>
Fri, 30 Dec 2016 01:38:28 +0000 (09:38 +0800)
committerZhang Shaowen <zhangshaowen@cmss.chinamobile.com>
Tue, 3 Jan 2017 03:43:02 +0000 (11:43 +0800)
Fixes: http://tracker.ceph.com/issues/18394
Signed-off-by: Zhang Shaowen <zhangshaowen@cmss.chinamobile.com>
src/rgw/rgw_lc.cc
src/rgw/rgw_lc.h
src/rgw/rgw_lc_s3.cc
src/rgw/rgw_op.cc

index 0aa1a23d3864acd0eb856b383d235f4917dee408..4760ea9d393da64bf53a45dafdea0f134b663709 100644 (file)
@@ -30,6 +30,18 @@ const char* LC_STATUS[] = {
 
 using namespace std;
 using namespace librados;
+
+bool LCRule::validate()
+{
+  if (id.length() > MAX_ID_LEN)
+    return false;
+  else if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0)
+    return false;
+  else if (expiration.get_days() <= 0)
+    return false;
+  return true;
+}
+
 void RGWLifecycleConfiguration::add_rule(LCRule *rule)
 {
   string id;
@@ -43,6 +55,49 @@ void RGWLifecycleConfiguration::_add_rule(LCRule *rule)
   prefix_map[rule->get_prefix()] = rule->get_expiration().get_days();
 }
 
+bool RGWLifecycleConfiguration::check_and_add_rule(LCRule *rule)
+{
+  if (!rule->validate())
+    return false;
+  string id;
+  rule->get_id(id);
+  if (rule_map.find(id) != rule_map.end())  //id shouldn't be the same 
+    return false;
+  rule_map.insert(pair<string, LCRule>(id, *rule));
+
+  auto ret = prefix_map.insert(pair<string, int>(rule->get_prefix(), rule->get_expiration().get_days()));
+  //Now prefix shouldn't be the same. When we add noncurrent expiration or other action, prefix may be same.
+  if (!ret.second)
+    return false;
+  return true;
+}
+
+//Rules are conflicted: if one rule's prefix starts with other rule's prefix, and these two rules
+//define same action(now only support expiration days). 
+bool RGWLifecycleConfiguration::validate() 
+{
+  if (prefix_map.size() < 2)
+    return true;
+  auto next_iter = prefix_map.begin();
+  auto cur_iter = next_iter++;
+  while (next_iter != prefix_map.end()) {
+    string c_pre = cur_iter->first;
+    string n_pre = next_iter->first;
+    if (c_pre.length() > n_pre.length()) {
+      if (c_pre.compare(0, n_pre.length(), n_pre) == 0) {
+        return false;
+      }
+    } else {
+      if (n_pre.compare(0, c_pre.length(), c_pre) == 0) {
+        return false;
+      }
+    }
+    ++next_iter;
+    ++cur_iter;
+  }
+  return true;
+}
+
 void *RGWLC::LCWorker::entry() {
   do {
     utime_t start = ceph_clock_now();
index d34f63dd3848818919c89f8347c9e32a9c2c0022..c33032f1c11320a438ca97ab6d62bc9f4291a112 100644 (file)
@@ -20,6 +20,7 @@
 
 using namespace std;
 #define HASH_PRIME 7877
+#define MAX_ID_LEN 255
 static string lc_oid_prefix = "lc";
 static string lc_index_lock_name = "lc_process";
 
@@ -102,6 +103,8 @@ public:
   void set_expiration(LCExpiration*_expiration) {
     expiration = *_expiration;
   }
+
+  bool validate();
   
   void encode(bufferlist& bl) const {
      ENCODE_START(1, 1, bl);
@@ -162,6 +165,10 @@ public:
 
   void add_rule(LCRule* rule);
 
+  bool check_and_add_rule(LCRule* rule);
+
+  bool validate();
+
   multimap<string, LCRule>& get_rule_map() { return rule_map; }
   map<string, int>& get_prefix_map() { return prefix_map; }
 /*
index cc05a2a35906f47e6c06cea1eb4e00be34bc48f6..c42b2975c598414fdb34b30a34bde9291f1288d6 100644 (file)
@@ -81,13 +81,11 @@ int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfigura
   multimap<string, LCRule>::iterator iter;
   for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
     LCRule& src_rule = iter->second;
-    bool rule_ok = true;
-
-    if (rule_ok) {
-      dest.add_rule(&src_rule);
-    }
+    if (!dest.check_and_add_rule(&src_rule))
+      return -EINVAL;
   }
-
+  if (!dest.validate())
+    return -EINVAL;
   return 0;
 }
 
index 29a272184ebc694038a1f9a86704703cdac0c653..9691dcb3c09f6fefb557908869e8c60bce7eda61 100644 (file)
@@ -4236,7 +4236,7 @@ void RGWPutLC::execute()
   ldout(s->cct, 15) << "read len=" << len << " data=" << (data ? data : "") << dendl;
 
   if (!parser.parse(data, len, 1)) {
-    op_ret = -EACCES;
+    op_ret = -EINVAL;
     return;
   }
   config = static_cast<RGWLifecycleConfiguration_S3 *>(parser.find_first("LifecycleConfiguration"));