Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / rgw / rgw_lc_s3.cc
1 #include <string.h>
2
3 #include <iostream>
4 #include <map>
5
6 #include "include/types.h"
7
8 #include "rgw_user.h"
9 #include "rgw_lc_s3.h"
10
11
12 #define dout_subsys ceph_subsys_rgw
13
14 using namespace std;
15
16 bool LCExpiration_S3::xml_end(const char * el) {
17   LCDays_S3 *lc_days = static_cast<LCDays_S3 *>(find_first("Days"));
18   LCDeleteMarker_S3 *lc_dm = static_cast<LCDeleteMarker_S3 *>(find_first("ExpiredObjectDeleteMarker"));
19   LCDate_S3 *lc_date = static_cast<LCDate_S3 *>(find_first("Date"));
20
21   if ((!lc_days && !lc_dm && !lc_date) || (lc_days && lc_dm) 
22       || (lc_days && lc_date) || (lc_dm && lc_date)) {
23     return false;
24   }
25   if (lc_days) {
26     days = lc_days->get_data();
27   } else if (lc_dm) {
28     dm_expiration = lc_dm->get_data().compare("true") == 0;
29     if (!dm_expiration) {
30       return false;
31     }
32   } else {
33     date = lc_date->get_data();
34     //We need return xml error according to S3
35     if (boost::none == ceph::from_iso_8601(date)) {
36       return false;
37     }
38   }
39   return true;
40 }
41
42 bool LCNoncurExpiration_S3::xml_end(const char *el) {
43   LCDays_S3 *lc_noncur_days = static_cast<LCDays_S3 *>(find_first("NoncurrentDays"));
44   if (!lc_noncur_days) {
45     return false;
46   }
47   days = lc_noncur_days->get_data();
48   return true;
49 }
50
51 bool LCMPExpiration_S3::xml_end(const char *el) {
52   LCDays_S3 *lc_mp_days = static_cast<LCDays_S3 *>(find_first("DaysAfterInitiation"));
53   if (!lc_mp_days) {
54     return false;
55   }
56   days = lc_mp_days->get_data();
57   return true;
58 }
59
60 bool RGWLifecycleConfiguration_S3::xml_end(const char *el) {
61   XMLObjIter iter = find("Rule");
62   LCRule_S3 *rule = static_cast<LCRule_S3 *>(iter.get_next());
63   while (rule) {
64     add_rule(rule);
65     rule = static_cast<LCRule_S3 *>(iter.get_next());
66   }
67   return true;
68 }
69
70 bool LCRule_S3::xml_end(const char *el) {
71   LCID_S3 *lc_id;
72   LCPrefix_S3 *lc_prefix;
73   LCStatus_S3 *lc_status;
74   LCExpiration_S3 *lc_expiration;
75   LCNoncurExpiration_S3 *lc_noncur_expiration;
76   LCMPExpiration_S3 *lc_mp_expiration;
77
78   id.clear();
79   prefix.clear();
80   status.clear();
81   dm_expiration = false;
82
83   // S3 generates a 48 bit random ID, maybe we could generate shorter IDs
84   static constexpr auto LC_ID_LENGTH = 48;
85
86   lc_id = static_cast<LCID_S3 *>(find_first("ID"));
87   if (lc_id){
88     id = lc_id->get_data();
89   } else {
90     gen_rand_alphanumeric_lower(nullptr, &id, LC_ID_LENGTH);
91   }
92
93
94   XMLObj *obj = find_first("Filter");
95
96   if (obj){
97     string _prefix;
98     RGWXMLDecoder::decode_xml("Prefix", _prefix, obj);
99     filter.set_prefix(std::move(_prefix));
100   } else {
101     // Ideally the following code should be deprecated and we should return
102     // False here, The new S3 LC configuration xml spec. makes Filter mandatory
103     // and Prefix optional. However older clients including boto2 still generate
104     // xml according to the older spec, where Prefix existed outside of Filter
105     // and S3 itself seems to be sloppy on enforcing the mandatory Filter
106     // argument. A day will come when S3 enforces their own xml-spec, but it is
107     // not this day
108
109     lc_prefix = static_cast<LCPrefix_S3 *>(find_first("Prefix"));
110
111     if (!lc_prefix){
112       return false;
113     }
114
115     prefix = lc_prefix->get_data();
116   }
117
118
119   lc_status = static_cast<LCStatus_S3 *>(find_first("Status"));
120   if (!lc_status)
121     return false;
122   status = lc_status->get_data();
123   if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0)
124     return false;
125
126   lc_expiration = static_cast<LCExpiration_S3 *>(find_first("Expiration"));
127   lc_noncur_expiration = static_cast<LCNoncurExpiration_S3 *>(find_first("NoncurrentVersionExpiration"));
128   lc_mp_expiration = static_cast<LCMPExpiration_S3 *>(find_first("AbortIncompleteMultipartUpload"));
129   if (!lc_expiration && !lc_noncur_expiration && !lc_mp_expiration) {
130     return false;
131   } else {
132     if (lc_expiration) {
133       if (lc_expiration->has_days()) {
134         expiration.set_days(lc_expiration->get_days_str());
135       } else if (lc_expiration->has_date()) {
136         expiration.set_date(lc_expiration->get_date());
137       } else {
138         dm_expiration = lc_expiration->get_dm_expiration();
139       }
140     }
141     if (lc_noncur_expiration) {
142       noncur_expiration = *lc_noncur_expiration;
143     }
144     if (lc_mp_expiration) {
145       mp_expiration = *lc_mp_expiration;
146     }
147   }
148
149   return true;
150 }
151
152 void LCRule_S3::to_xml(CephContext *cct, ostream& out) {
153   out << "<Rule>" ;
154   out << "<ID>" << id << "</ID>";
155   if (!filter.empty()) {
156     LCFilter_S3& lc_filter = static_cast<LCFilter_S3&>(filter);
157     lc_filter.to_xml(out);
158   } else {
159     out << "<Prefix>" << prefix << "</Prefix>";
160   }
161   out << "<Status>" << status << "</Status>";
162   if (!expiration.empty() || dm_expiration) {
163     LCExpiration_S3 expir(expiration.get_days_str(), expiration.get_date(), dm_expiration);
164     expir.to_xml(out);
165   }
166   if (!noncur_expiration.empty()) {
167     LCNoncurExpiration_S3& noncur_expir = static_cast<LCNoncurExpiration_S3&>(noncur_expiration);
168     noncur_expir.to_xml(out);
169   }
170   if (!mp_expiration.empty()) {
171     LCMPExpiration_S3& mp_expir = static_cast<LCMPExpiration_S3&>(mp_expiration);
172     mp_expir.to_xml(out);
173   }
174   out << "</Rule>";
175 }
176
177 int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfiguration& dest)
178 {
179   int ret = 0;
180   multimap<string, LCRule>::iterator iter;
181   for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
182     LCRule& src_rule = iter->second;
183     ret = dest.check_and_add_rule(&src_rule);
184     if (ret < 0)
185       return ret;
186   }
187   if (!dest.valid()) {
188     ret = -ERR_INVALID_REQUEST;
189   }
190   return ret;
191 }
192
193 void RGWLifecycleConfiguration_S3::dump_xml(Formatter *f) const
194 {
195         f->open_object_section_in_ns("LifecycleConfiguration", XMLNS_AWS_S3);
196
197     for (auto iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
198                 const LCRule_S3& rule = static_cast<const LCRule_S3&>(iter->second);
199                 rule.dump_xml(f);
200         }
201
202         f->close_section(); // Lifecycle
203 }
204
205 XMLObj *RGWLCXMLParser_S3::alloc_obj(const char *el)
206 {
207   XMLObj * obj = NULL;
208   if (strcmp(el, "LifecycleConfiguration") == 0) {
209     obj = new RGWLifecycleConfiguration_S3(cct);
210   } else if (strcmp(el, "Rule") == 0) {
211     obj = new LCRule_S3();
212   } else if (strcmp(el, "ID") == 0) {
213     obj = new LCID_S3();
214   } else if (strcmp(el, "Prefix") == 0) {
215     obj = new LCPrefix_S3();
216   } else if (strcmp(el, "Status") == 0) {
217     obj = new LCStatus_S3();
218   } else if (strcmp(el, "Expiration") == 0) {
219     obj = new LCExpiration_S3();
220   } else if (strcmp(el, "Days") == 0) {
221     obj = new LCDays_S3();
222   } else if (strcmp(el, "Date") == 0) {
223     obj = new LCDate_S3();
224   } else if (strcmp(el, "ExpiredObjectDeleteMarker") == 0) {
225     obj = new LCDeleteMarker_S3();
226   } else if (strcmp(el, "NoncurrentVersionExpiration") == 0) {
227     obj = new LCNoncurExpiration_S3();
228   } else if (strcmp(el, "NoncurrentDays") == 0) {
229     obj = new LCDays_S3();
230   } else if (strcmp(el, "AbortIncompleteMultipartUpload") == 0) {
231     obj = new LCMPExpiration_S3();
232   } else if (strcmp(el, "DaysAfterInitiation") == 0) {
233     obj = new LCDays_S3();
234   }
235   return obj;
236 }