]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/test_rgw_admin_log.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / test / test_rgw_admin_log.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14 #include <iostream>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <time.h>
20 #include <sys/wait.h>
21 #include <unistd.h>
22 #include <fstream>
23 #include <map>
24 #include <list>
25 extern "C"{
26 #include <curl/curl.h>
27 }
28 #include "common/ceph_crypto.h"
29 #include "include/str_list.h"
30 #include "common/ceph_json.h"
31 #include "common/code_environment.h"
32 #include "common/ceph_argparse.h"
33 #include "common/Finisher.h"
34 #include "global/global_init.h"
35 #include "rgw/rgw_common.h"
36 #include "rgw/rgw_datalog.h"
37 #include "rgw/rgw_mdlog.h"
38 #include "rgw/rgw_bucket.h"
39 #include "rgw/rgw_rados.h"
40 #include "include/utime.h"
41 #include "include/object.h"
42 #include <gtest/gtest.h>
43
44 using namespace std;
45
46 #define CURL_VERBOSE 0
47 #define HTTP_RESPONSE_STR "RespCode"
48 #define CEPH_CRYPTO_HMACSHA1_DIGESTSIZE 20
49 #define RGW_ADMIN_RESP_PATH "/tmp/.test_rgw_admin_resp"
50 #define TEST_BUCKET_NAME "test_bucket"
51 #define TEST_BUCKET_OBJECT "test_object"
52 #define TEST_BUCKET_OBJECT_1 "test_object1"
53 #define TEST_BUCKET_OBJECT_SIZE 1024
54
55 static string uid = "ceph";
56 static string display_name = "CEPH";
57
58 extern "C" int ceph_armor(char *dst, const char *dst_end,
59 const char *src, const char *end);
60 static void print_usage(char *exec){
61 cout << "Usage: " << exec << " <Options>\n";
62 cout << "Options:\n"
63 "-g <gw-ip> - The ip address of the gateway\n"
64 "-p <gw-port> - The port number of the gateway\n"
65 "-c <ceph.conf> - Absolute path of ceph config file\n"
66 "-rgw-admin <path/to/radosgw-admin> - radosgw-admin absolute path\n";
67 }
68
69 namespace admin_log {
70 class test_helper {
71 private:
72 string host;
73 string port;
74 string creds;
75 string rgw_admin_path;
76 string conf_path;
77 CURL *curl_inst;
78 map<string, string> response;
79 list<string> extra_hdrs;
80 string *resp_data;
81 unsigned resp_code;
82 public:
83 test_helper() : resp_data(NULL){
84 curl_global_init(CURL_GLOBAL_ALL);
85 }
86 ~test_helper(){
87 curl_global_cleanup();
88 }
89 int send_request(string method, string uri,
90 size_t (*function)(void *,size_t,size_t,void *) = 0,
91 void *ud = 0, size_t length = 0);
92 int extract_input(int argc, char *argv[]);
93 string& get_response(string hdr){
94 return response[hdr];
95 }
96 void set_extra_header(string hdr){
97 extra_hdrs.push_back(hdr);
98 }
99 void set_response(char *val);
100 void set_response_data(char *data, size_t len){
101 if(resp_data) delete resp_data;
102 resp_data = new string(data, len);
103 }
104 string& get_rgw_admin_path() {
105 return rgw_admin_path;
106 }
107 string& get_ceph_conf_path() {
108 return conf_path;
109 }
110 void set_creds(string& c) {
111 creds = c;
112 }
113 const string *get_response_data(){return resp_data;}
114 unsigned get_resp_code(){return resp_code;}
115 };
116
117 int test_helper::extract_input(int argc, char *argv[]){
118 #define ERR_CHECK_NEXT_PARAM(o) \
119 if(((int)loop + 1) >= argc)return -1; \
120 else o = argv[loop+1];
121
122 for(unsigned loop = 1;loop < (unsigned)argc; loop += 2){
123 if(strcmp(argv[loop], "-g") == 0){
124 ERR_CHECK_NEXT_PARAM(host);
125 }else if(strcmp(argv[loop],"-p") == 0){
126 ERR_CHECK_NEXT_PARAM(port);
127 }else if(strcmp(argv[loop], "-c") == 0){
128 ERR_CHECK_NEXT_PARAM(conf_path);
129 }else if(strcmp(argv[loop], "-rgw-admin") == 0){
130 ERR_CHECK_NEXT_PARAM(rgw_admin_path);
131 }else return -1;
132 }
133 if(!host.length() || !rgw_admin_path.length())
134 return -1;
135 return 0;
136 }
137
138 void test_helper::set_response(char *r){
139 string sr(r), h, v;
140 size_t off = sr.find(": ");
141 if(off != string::npos){
142 h.assign(sr, 0, off);
143 v.assign(sr, off + 2, sr.find("\r\n") - (off+2));
144 }else{
145 /*Could be the status code*/
146 if(sr.find("HTTP/") != string::npos){
147 h.assign(HTTP_RESPONSE_STR);
148 off = sr.find(" ");
149 v.assign(sr, off + 1, sr.find("\r\n") - (off + 1));
150 resp_code = atoi((v.substr(0, 3)).c_str());
151 }
152 }
153 response[h] = v;
154 }
155
156 size_t write_header(void *ptr, size_t size, size_t nmemb, void *ud){
157 test_helper *h = static_cast<test_helper *>(ud);
158 h->set_response((char *)ptr);
159 return size*nmemb;
160 }
161
162 size_t write_data(void *ptr, size_t size, size_t nmemb, void *ud){
163 test_helper *h = static_cast<test_helper *>(ud);
164 h->set_response_data((char *)ptr, size*nmemb);
165 return size*nmemb;
166 }
167
168 static inline void buf_to_hex(const unsigned char *buf, int len, char *str)
169 {
170 int i;
171 str[0] = '\0';
172 for (i = 0; i < len; i++) {
173 sprintf(&str[i*2], "%02x", (int)buf[i]);
174 }
175 }
176
177 static void calc_hmac_sha1(const char *key, int key_len,
178 const char *msg, int msg_len, char *dest)
179 /* destination should be CEPH_CRYPTO_HMACSHA1_DIGESTSIZE bytes long */
180 {
181 ceph::crypto::HMACSHA1 hmac((const unsigned char *)key, key_len);
182 hmac.Update((const unsigned char *)msg, msg_len);
183 hmac.Final((unsigned char *)dest);
184
185 char hex_str[(CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2) + 1];
186 admin_log::buf_to_hex((unsigned char *)dest, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE, hex_str);
187 }
188
189 static int get_s3_auth(const string &method, string creds, const string &date, string res, string& out){
190 string aid, secret, auth_hdr;
191 string tmp_res;
192 size_t off = creds.find(":");
193 out = "";
194 if(off != string::npos){
195 aid.assign(creds, 0, off);
196 secret.assign(creds, off + 1, string::npos);
197
198 /*sprintf(auth_hdr, "%s\n\n\n%s\n%s", req_type, date, res);*/
199 char hmac_sha1[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
200 char b64[65]; /* 64 is really enough */
201 size_t off = res.find("?");
202 if(off == string::npos)
203 tmp_res = res;
204 else
205 tmp_res.assign(res, 0, off);
206 auth_hdr.append(method + string("\n\n\n") + date + string("\n") + tmp_res);
207 admin_log::calc_hmac_sha1(secret.c_str(), secret.length(),
208 auth_hdr.c_str(), auth_hdr.length(), hmac_sha1);
209 int ret = ceph_armor(b64, b64 + 64, hmac_sha1,
210 hmac_sha1 + CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
211 if (ret < 0) {
212 cout << "ceph_armor failed\n";
213 return -1;
214 }
215 b64[ret] = 0;
216 out.append(aid + string(":") + b64);
217 }else return -1;
218 return 0;
219 }
220
221 void get_date(string& d){
222 struct timeval tv;
223 char date[64];
224 struct tm tm;
225 char *days[] = {(char *)"Sun", (char *)"Mon", (char *)"Tue",
226 (char *)"Wed", (char *)"Thu", (char *)"Fri",
227 (char *)"Sat"};
228 char *months[] = {(char *)"Jan", (char *)"Feb", (char *)"Mar",
229 (char *)"Apr", (char *)"May", (char *)"Jun",
230 (char *)"Jul",(char *) "Aug", (char *)"Sep",
231 (char *)"Oct", (char *)"Nov", (char *)"Dec"};
232 gettimeofday(&tv, NULL);
233 gmtime_r(&tv.tv_sec, &tm);
234 sprintf(date, "%s, %d %s %d %d:%d:%d GMT",
235 days[tm.tm_wday],
236 tm.tm_mday, months[tm.tm_mon],
237 tm.tm_year + 1900,
238 tm.tm_hour, tm.tm_min, tm.tm_sec);
239 d = date;
240 }
241
242 int test_helper::send_request(string method, string res,
243 size_t (*read_function)( void *,size_t,size_t,void *),
244 void *ud,
245 size_t length){
246 string url;
247 string auth, date;
248 url.append(string("http://") + host);
249 if(port.length() > 0)url.append(string(":") + port);
250 url.append(res);
251 curl_inst = curl_easy_init();
252 if(curl_inst){
253 curl_easy_setopt(curl_inst, CURLOPT_URL, url.c_str());
254 curl_easy_setopt(curl_inst, CURLOPT_CUSTOMREQUEST, method.c_str());
255 curl_easy_setopt(curl_inst, CURLOPT_VERBOSE, CURL_VERBOSE);
256 curl_easy_setopt(curl_inst, CURLOPT_HEADERFUNCTION, admin_log::write_header);
257 curl_easy_setopt(curl_inst, CURLOPT_WRITEHEADER, (void *)this);
258 curl_easy_setopt(curl_inst, CURLOPT_WRITEFUNCTION, admin_log::write_data);
259 curl_easy_setopt(curl_inst, CURLOPT_WRITEDATA, (void *)this);
260 if(read_function){
261 curl_easy_setopt(curl_inst, CURLOPT_READFUNCTION, read_function);
262 curl_easy_setopt(curl_inst, CURLOPT_READDATA, (void *)ud);
263 curl_easy_setopt(curl_inst, CURLOPT_UPLOAD, 1L);
264 curl_easy_setopt(curl_inst, CURLOPT_INFILESIZE_LARGE, (curl_off_t)length);
265 }
266
267 get_date(date);
268 string http_date;
269 http_date.append(string("Date: ") + date);
270
271 string s3auth;
272 if (admin_log::get_s3_auth(method, creds, date, res, s3auth) < 0)
273 return -1;
274 auth.append(string("Authorization: AWS ") + s3auth);
275
276 struct curl_slist *slist = NULL;
277 slist = curl_slist_append(slist, auth.c_str());
278 slist = curl_slist_append(slist, http_date.c_str());
279 for(list<string>::iterator it = extra_hdrs.begin();
280 it != extra_hdrs.end(); ++it){
281 slist = curl_slist_append(slist, (*it).c_str());
282 }
283 if(read_function)
284 curl_slist_append(slist, "Expect:");
285 curl_easy_setopt(curl_inst, CURLOPT_HTTPHEADER, slist);
286
287 response.erase(response.begin(), response.end());
288 extra_hdrs.erase(extra_hdrs.begin(), extra_hdrs.end());
289 CURLcode res = curl_easy_perform(curl_inst);
290 if(res != CURLE_OK){
291 cout << "Curl perform failed for " << url << ", res: " <<
292 curl_easy_strerror(res) << "\n";
293 return -1;
294 }
295 curl_slist_free_all(slist);
296 }
297 curl_easy_cleanup(curl_inst);
298 return 0;
299 }
300 };
301
302 admin_log::test_helper *g_test;
303 Finisher *finisher;
304
305 int run_rgw_admin(string& cmd, string& resp) {
306 pid_t pid;
307 pid = fork();
308 if (pid == 0) {
309 /* child */
310 list<string> l;
311 get_str_list(cmd, " \t", l);
312 char *argv[l.size()];
313 unsigned loop = 1;
314
315 argv[0] = (char *)"radosgw-admin";
316 for (list<string>::iterator it = l.begin();
317 it != l.end(); ++it) {
318 argv[loop++] = (char *)(*it).c_str();
319 }
320 argv[loop] = NULL;
321 if (!freopen(RGW_ADMIN_RESP_PATH, "w+", stdout)) {
322 cout << "Unable to open stdout file" << std::endl;
323 }
324 execv((g_test->get_rgw_admin_path()).c_str(), argv);
325 } else if (pid > 0) {
326 int status;
327 waitpid(pid, &status, 0);
328 if (WIFEXITED(status)) {
329 if(WEXITSTATUS(status) != 0) {
330 cout << "Child exited with status " << WEXITSTATUS(status) << std::endl;
331 return -1;
332 }
333 }
334 ifstream in;
335 struct stat st;
336
337 if (stat(RGW_ADMIN_RESP_PATH, &st) < 0) {
338 cout << "Error stating the admin response file, errno " << errno << std::endl;
339 return -1;
340 } else {
341 char *data = (char *)malloc(st.st_size + 1);
342 in.open(RGW_ADMIN_RESP_PATH);
343 in.read(data, st.st_size);
344 in.close();
345 data[st.st_size] = 0;
346 resp = data;
347 free(data);
348 unlink(RGW_ADMIN_RESP_PATH);
349 /* cout << "radosgw-admin " << cmd << ": " << resp << std::endl; */
350 }
351 } else
352 return -1;
353 return 0;
354 }
355
356 int get_creds(string& json, string& creds) {
357 JSONParser parser;
358 if(!parser.parse(json.c_str(), json.length())) {
359 cout << "Error parsing create user response" << std::endl;
360 return -1;
361 }
362
363 RGWUserInfo info;
364 decode_json_obj(info, &parser);
365 creds = "";
366 for(map<string, RGWAccessKey>::iterator it = info.access_keys.begin();
367 it != info.access_keys.end(); ++it) {
368 RGWAccessKey _k = it->second;
369 /*cout << "accesskeys [ " << it->first << " ] = " <<
370 "{ " << _k.id << ", " << _k.key << ", " << _k.subuser << "}" << std::endl;*/
371 creds.append(it->first + string(":") + _k.key);
372 break;
373 }
374 return 0;
375 }
376
377 int user_create(string& uid, string& display_name, bool set_creds = true) {
378 stringstream ss;
379 string creds;
380 ss << "-c " << g_test->get_ceph_conf_path() << " user create --uid=" << uid
381 << " --display-name=" << display_name;
382
383 string out;
384 string cmd = ss.str();
385 if(run_rgw_admin(cmd, out) != 0) {
386 cout << "Error creating user" << std::endl;
387 return -1;
388 }
389 get_creds(out, creds);
390 if(set_creds)
391 g_test->set_creds(creds);
392 return 0;
393 }
394
395 int user_info(string& uid, string& display_name, RGWUserInfo& uinfo) {
396 stringstream ss;
397 ss << "-c " << g_test->get_ceph_conf_path() << " user info --uid=" << uid
398 << " --display-name=" << display_name;
399
400 string out;
401 string cmd = ss.str();
402 if(run_rgw_admin(cmd, out) != 0) {
403 cout << "Error reading user information" << std::endl;
404 return -1;
405 }
406 JSONParser parser;
407 if(!parser.parse(out.c_str(), out.length())) {
408 cout << "Error parsing create user response" << std::endl;
409 return -1;
410 }
411 decode_json_obj(uinfo, &parser);
412 return 0;
413 }
414
415 int user_rm(string& uid, string& display_name) {
416 stringstream ss;
417 ss << "-c " << g_test->get_ceph_conf_path() <<
418 " metadata rm --metadata-key=user:" << uid;
419
420 string out;
421 string cmd = ss.str();
422 if(run_rgw_admin(cmd, out) != 0) {
423 cout << "Error removing user" << std::endl;
424 return -1;
425 }
426 return 0;
427 }
428
429 int caps_add(const char * name, const char *perm) {
430 stringstream ss;
431
432 ss << "-c " << g_test->get_ceph_conf_path() << " caps add --caps=" <<
433 name << "=" << perm << " --uid=" << uid;
434 string out;
435 string cmd = ss.str();
436 if(run_rgw_admin(cmd, out) != 0) {
437 cout << "Error creating user" << std::endl;
438 return -1;
439 }
440 return 0;
441 }
442
443 int caps_rm(const char * name, const char *perm) {
444 stringstream ss;
445
446 ss << "-c " << g_test->get_ceph_conf_path() << " caps rm --caps=" <<
447 name << "=" << perm << " --uid=" << uid;
448 string out;
449 string cmd = ss.str();
450 if(run_rgw_admin(cmd, out) != 0) {
451 cout << "Error creating user" << std::endl;
452 return -1;
453 }
454 return 0;
455 }
456
457 static int create_bucket(void){
458 g_test->send_request(string("PUT"), string("/" TEST_BUCKET_NAME));
459 if(g_test->get_resp_code() != 200U){
460 cout << "Error creating bucket, http code " << g_test->get_resp_code();
461 return -1;
462 }
463 return 0;
464 }
465
466 static int delete_bucket(void){
467 g_test->send_request(string("DELETE"), string("/" TEST_BUCKET_NAME));
468 if(g_test->get_resp_code() != 204U){
469 cout << "Error deleting bucket, http code " << g_test->get_resp_code();
470 return -1;
471 }
472 return 0;
473 }
474
475 size_t read_dummy_post(void *ptr, size_t s, size_t n, void *ud) {
476 int dummy = 0;
477 memcpy(ptr, &dummy, sizeof(dummy));
478 return sizeof(dummy);
479 }
480
481 size_t read_bucket_object(void *ptr, size_t s, size_t n, void *ud) {
482 memcpy(ptr, ud, TEST_BUCKET_OBJECT_SIZE);
483 return TEST_BUCKET_OBJECT_SIZE;
484 }
485
486 static int put_bucket_obj(const char *obj_name, char *data, unsigned len) {
487 string req = "/" TEST_BUCKET_NAME"/";
488 req.append(obj_name);
489 g_test->send_request(string("PUT"), req,
490 read_bucket_object, (void *)data, (size_t)len);
491 if (g_test->get_resp_code() != 200U) {
492 cout << "Errror sending object to the bucket, http_code " << g_test->get_resp_code();
493 return -1;
494 }
495 return 0;
496 }
497
498 static int read_bucket_obj(const char *obj_name) {
499 string req = "/" TEST_BUCKET_NAME"/";
500 req.append(obj_name);
501 g_test->send_request(string("GET"), req);
502 if (g_test->get_resp_code() != 200U) {
503 cout << "Errror sending object to the bucket, http_code " << g_test->get_resp_code();
504 return -1;
505 }
506 return 0;
507 }
508
509 static int delete_obj(const char *obj_name) {
510 string req = "/" TEST_BUCKET_NAME"/";
511 req.append(obj_name);
512 g_test->send_request(string("DELETE"), req);
513 if (g_test->get_resp_code() != 204U) {
514 cout << "Errror deleting object from bucket, http_code " << g_test->get_resp_code();
515 return -1;
516 }
517 return 0;
518 }
519
520 int get_formatted_time(string& ret) {
521 struct tm *tm = NULL;
522 char str_time[200];
523 const char *format = "%Y-%m-%d%%20%H:%M:%S";
524 time_t t;
525
526 t = time(NULL);
527 tm = gmtime(&t);
528 if(!tm) {
529 cerr << "Error returned by gmtime\n";
530 return -1;
531 }
532 if (strftime(str_time, sizeof(str_time), format, tm) == 0) {
533 cerr << "Error returned by strftime\n";
534 return -1;
535 }
536 ret = str_time;
537 return 0;
538 }
539
540 int parse_json_resp(JSONParser &parser) {
541 string *resp;
542 resp = (string *)g_test->get_response_data();
543 if(!resp)
544 return -1;
545 if(!parser.parse(resp->c_str(), resp->length())) {
546 cout << "Error parsing create user response" << std::endl;
547 return -1;
548 }
549 return 0;
550 }
551
552 struct cls_log_entry_json {
553 string section;
554 string name;
555 utime_t timestamp;
556 RGWMetadataLogData log_data;
557 };
558
559 static int decode_json(JSONObj *obj, RGWMetadataLogData &data) {
560 JSONObj *jo;
561
562 jo = obj->find_obj("read_version");
563 if (!jo)
564 return -1;
565 data.read_version.decode_json(obj);
566 data.write_version.decode_json(obj);
567
568 jo = obj->find_obj("status");
569 if (!jo)
570 return -1;
571 JSONDecoder::decode_json("status", data, jo);
572 return 0;
573 }
574
575 static int decode_json(JSONObj *obj, cls_log_entry_json& ret) {
576 JSONDecoder::decode_json("section", ret.section, obj);
577 JSONDecoder::decode_json("name", ret.name, obj);
578 JSONObj *jo = obj->find_obj("data");
579 if(!jo)
580 return 0;
581 return decode_json(jo, ret.log_data);
582 }
583
584 static int get_log_list(list<cls_log_entry_json> &entries) {
585 JSONParser parser;
586 if (parse_json_resp(parser) != 0)
587 return -1;
588 if (!parser.is_array())
589 return -1;
590
591 vector<string> l;
592 l = parser.get_array_elements();
593 int loop = 0;
594 for(vector<string>::iterator it = l.begin();
595 it != l.end(); ++it, loop++) {
596 JSONParser jp;
597 cls_log_entry_json entry;
598
599 if(!jp.parse((*it).c_str(), (*it).length())) {
600 cerr << "Error parsing log json object" << std::endl;
601 return -1;
602 }
603 EXPECT_EQ(decode_json((JSONObj *)&jp, entry), 0);
604 entries.push_back(entry);
605 }
606 return 0;
607 }
608
609 struct cls_bilog_entry {
610 string op_id;
611 string op_tag;
612 string op;
613 string object;
614 string status;
615 unsigned index_ver;
616 };
617
618 static int decode_json(JSONObj *obj, cls_bilog_entry& ret) {
619 JSONDecoder::decode_json("op_id", ret.op_id, obj);
620 JSONDecoder::decode_json("op_tag", ret.op_tag, obj);
621 JSONDecoder::decode_json("op", ret.op, obj);
622 JSONDecoder::decode_json("object", ret.object, obj);
623 JSONDecoder::decode_json("state", ret.status, obj);
624 JSONDecoder::decode_json("index_ver", ret.index_ver, obj);
625 return 0;
626 }
627
628 static int get_bilog_list(list<cls_bilog_entry> &entries) {
629 JSONParser parser;
630 if (parse_json_resp(parser) != 0)
631 return -1;
632 if (!parser.is_array())
633 return -1;
634
635 vector<string> l;
636 l = parser.get_array_elements();
637 int loop = 0;
638 for(vector<string>::iterator it = l.begin();
639 it != l.end(); ++it, loop++) {
640 JSONParser jp;
641 cls_bilog_entry entry;
642
643 if(!jp.parse((*it).c_str(), (*it).length())) {
644 cerr << "Error parsing log json object" << std::endl;
645 return -1;
646 }
647 EXPECT_EQ(decode_json((JSONObj *)&jp, entry), 0);
648 entries.push_back(entry);
649 }
650 return 0;
651 }
652
653 static int decode_json(JSONObj *obj, rgw_data_change& ret) {
654 string entity;
655
656 JSONDecoder::decode_json("entity_type", entity, obj);
657 if (entity.compare("bucket") == 0)
658 ret.entity_type = ENTITY_TYPE_BUCKET;
659 JSONDecoder::decode_json("key", ret.key, obj);
660 return 0;
661 }
662
663 static int get_datalog_list(list<rgw_data_change> &entries) {
664 JSONParser parser;
665
666 if (parse_json_resp(parser) != 0)
667 return -1;
668 if (!parser.is_array())
669 return -1;
670
671 vector<string> l;
672 l = parser.get_array_elements();
673 int loop = 0;
674 for(vector<string>::iterator it = l.begin();
675 it != l.end(); ++it, loop++) {
676 JSONParser jp;
677 rgw_data_change entry;
678
679 if(!jp.parse((*it).c_str(), (*it).length())) {
680 cerr << "Error parsing log json object" << std::endl;
681 return -1;
682 }
683 EXPECT_EQ(decode_json((JSONObj *)&jp, entry), 0);
684 entries.push_back(entry);
685 }
686 return 0;
687 }
688
689 unsigned get_mdlog_shard_id(string& key, int max_shards) {
690 string section = "user";
691 uint32_t val = ceph_str_hash_linux(key.c_str(), key.size());
692 val ^= ceph_str_hash_linux(section.c_str(), section.size());
693 return (unsigned)(val % max_shards);
694 }
695
696 unsigned get_datalog_shard_id(const char *bucket_name, int max_shards) {
697 uint32_t r = ceph_str_hash_linux(bucket_name, strlen(bucket_name)) % max_shards;
698 return (int)r;
699 }
700
701 TEST(TestRGWAdmin, datalog_list) {
702 string start_time,
703 end_time;
704 const char *cname = "datalog",
705 *perm = "*";
706 string rest_req;
707 unsigned shard_id = get_datalog_shard_id(TEST_BUCKET_NAME, g_ceph_context->_conf->rgw_data_log_num_shards);
708 stringstream ss;
709 list<rgw_data_change> entries;
710
711 ASSERT_EQ(get_formatted_time(start_time), 0);
712 ASSERT_EQ(0, user_create(uid, display_name));
713 ASSERT_EQ(0, caps_add(cname, perm));
714
715 rest_req = "/admin/log?type=data";
716 g_test->send_request(string("GET"), rest_req);
717 EXPECT_EQ(200U, g_test->get_resp_code());
718 JSONParser parser;
719 int num_objects;
720 EXPECT_EQ (parse_json_resp(parser), 0);
721 JSONDecoder::decode_json("num_objects", num_objects, (JSONObj *)&parser);
722 ASSERT_EQ(num_objects,g_ceph_context->_conf->rgw_data_log_num_shards);
723
724 sleep(1);
725 ASSERT_EQ(0, create_bucket());
726
727 char *bucket_obj = (char *)calloc(1, TEST_BUCKET_OBJECT_SIZE);
728 ASSERT_TRUE(bucket_obj != NULL);
729 EXPECT_EQ(put_bucket_obj(TEST_BUCKET_OBJECT, bucket_obj, TEST_BUCKET_OBJECT_SIZE), 0);
730 sleep(1);
731 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time;
732 rest_req = ss.str();
733 g_test->send_request(string("GET"), rest_req);
734 EXPECT_EQ(200U, g_test->get_resp_code());
735 entries.clear();
736 get_datalog_list(entries);
737 EXPECT_EQ(1U, entries.size());
738 if (entries.size() == 1) {
739 rgw_data_change entry = *(entries.begin());
740 EXPECT_EQ(entry.entity_type, ENTITY_TYPE_BUCKET);
741 EXPECT_EQ(entry.key.compare(TEST_BUCKET_NAME), 0);
742 }
743 ASSERT_EQ(0, delete_obj(TEST_BUCKET_OBJECT));
744 sleep(1);
745 ASSERT_EQ(get_formatted_time(end_time), 0);
746 ss.str("");
747 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time;
748 rest_req = ss.str();
749 g_test->send_request(string("GET"), rest_req);
750 EXPECT_EQ(200U, g_test->get_resp_code());
751 entries.clear();
752 get_datalog_list(entries);
753 EXPECT_EQ(1U, entries.size());
754 if (entries.size() == 1) {
755 list<rgw_data_change>::iterator it = (entries.begin());
756 EXPECT_EQ((*it).entity_type, ENTITY_TYPE_BUCKET);
757 EXPECT_EQ((*it).key.compare(TEST_BUCKET_NAME), 0);
758 }
759
760 sleep(1);
761 EXPECT_EQ(put_bucket_obj(TEST_BUCKET_OBJECT, bucket_obj, TEST_BUCKET_OBJECT_SIZE), 0);
762 free(bucket_obj);
763 sleep(20);
764 ss.str("");
765 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time;
766 rest_req = ss.str();
767 g_test->send_request(string("GET"), rest_req);
768 EXPECT_EQ(200U, g_test->get_resp_code());
769 entries.clear();
770 get_datalog_list(entries);
771 EXPECT_EQ(2U, entries.size());
772 if (entries.size() == 2) {
773 list<rgw_data_change>::iterator it = (entries.begin());
774 EXPECT_EQ((*it).entity_type, ENTITY_TYPE_BUCKET);
775 EXPECT_EQ((*it).key.compare(TEST_BUCKET_NAME), 0);
776 ++it;
777 EXPECT_EQ((*it).entity_type, ENTITY_TYPE_BUCKET);
778 EXPECT_EQ((*it).key.compare(TEST_BUCKET_NAME), 0);
779 }
780
781 ss.str("");
782 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time
783 << "&max-entries=1";
784 rest_req = ss.str();
785 g_test->send_request(string("GET"), rest_req);
786 EXPECT_EQ(200U, g_test->get_resp_code());
787 entries.clear();
788 get_datalog_list(entries);
789 EXPECT_EQ(1U, entries.size());
790
791 ss.str("");
792 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time
793 << "&end-time=" << end_time;
794 rest_req = ss.str();
795 g_test->send_request(string("GET"), rest_req);
796 EXPECT_EQ(200U, g_test->get_resp_code());
797 entries.clear();
798 get_datalog_list(entries);
799 EXPECT_EQ(1U, entries.size());
800
801 ASSERT_EQ(0, caps_rm(cname, perm));
802 perm = "read";
803 ASSERT_EQ(0, caps_add(cname, perm));
804 ss.str("");
805 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time;
806 rest_req = ss.str();
807 g_test->send_request(string("GET"), rest_req);
808 EXPECT_EQ(200U, g_test->get_resp_code());
809 ASSERT_EQ(0, caps_rm(cname, perm));
810 ss.str("");
811 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time;
812 rest_req = ss.str();
813
814 g_test->send_request(string("GET"), rest_req);
815 EXPECT_EQ(403U, g_test->get_resp_code());
816
817 ASSERT_EQ(0, delete_obj(TEST_BUCKET_OBJECT));
818 ASSERT_EQ(0, delete_bucket());
819 ASSERT_EQ(0, user_rm(uid, display_name));
820 }
821
822 TEST(TestRGWAdmin, datalog_lock_unlock) {
823 const char *cname = "datalog",
824 *perm = "*";
825 string rest_req;
826
827 ASSERT_EQ(0, user_create(uid, display_name));
828 ASSERT_EQ(0, caps_add(cname, perm));
829
830 rest_req = "/admin/log?type=data&lock&length=3&locker-id=ceph&zone-id=1";
831 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
832 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
833
834 rest_req = "/admin/log?type=data&lock&id=3&locker-id=ceph&zone-id=1";
835 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
836 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
837
838 rest_req = "/admin/log?type=data&lock&length=3&id=1&zone-id=1";
839 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
840 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
841
842 rest_req = "/admin/log?type=data&lock&length=3&id=1&locker-id=1";
843 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
844 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
845
846 rest_req = "/admin/log?type=data&unlock&id=1&zone-id=1";
847 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
848 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
849
850 rest_req = "/admin/log?type=data&unlock&locker-id=ceph&zone-id=1";
851 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
852 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
853
854 rest_req = "/admin/log?type=data&unlock&locker-id=ceph&id=1";
855 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
856 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
857
858 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph&zone-id=1";
859 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
860 EXPECT_EQ(200U, g_test->get_resp_code());
861
862 rest_req = "/admin/log?type=data&unlock&id=1&locker-id=ceph&zone-id=1";
863 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
864 EXPECT_EQ(200U, g_test->get_resp_code());
865
866 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph1&zone-id=1";
867 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
868 EXPECT_EQ(200U, g_test->get_resp_code());
869
870 rest_req = "/admin/log?type=data&unlock&id=1&locker-id=ceph1&zone-id=1";
871 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
872 EXPECT_EQ(200U, g_test->get_resp_code());
873
874 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph&zone-id=1";
875 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
876 EXPECT_EQ(200U, g_test->get_resp_code());
877 utime_t sleep_time(3, 0);
878
879 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph1&zone-id=1";
880 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
881 EXPECT_EQ(500U, g_test->get_resp_code());
882
883 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph1&zone-id=2";
884 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
885 EXPECT_EQ(500U, g_test->get_resp_code());
886
887 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph&zone-id=1";
888 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
889 EXPECT_EQ(200U, g_test->get_resp_code());
890 sleep_time.sleep();
891
892 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph1&zone-id=1";
893 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
894 EXPECT_EQ(200U, g_test->get_resp_code());
895
896 rest_req = "/admin/log?type=data&unlock&id=1&locker-id=ceph1&zone-id=1";
897 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
898 EXPECT_EQ(200U, g_test->get_resp_code());
899
900 ASSERT_EQ(0, caps_rm(cname, perm));
901 perm = "read";
902 ASSERT_EQ(0, caps_add(cname, perm));
903 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph&zone-id=1";
904 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
905 EXPECT_EQ(403U, g_test->get_resp_code());
906
907 rest_req = "/admin/log?type=data&unlock&id=1&locker-id=ceph&zone-id=1";
908 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
909 EXPECT_EQ(403U, g_test->get_resp_code());
910
911 ASSERT_EQ(0, caps_rm(cname, perm));
912 perm = "write";
913 ASSERT_EQ(0, caps_add(cname, perm));
914 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph&zone-id=1";
915 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
916 EXPECT_EQ(200U, g_test->get_resp_code());
917
918 rest_req = "/admin/log?type=data&unlock&id=1&locker-id=ceph&zone-id=1";
919 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
920 EXPECT_EQ(200U, g_test->get_resp_code());
921
922 ASSERT_EQ(0, caps_rm(cname, perm));
923 rest_req = "/admin/log?type=data&lock&id=1&length=3&locker-id=ceph&zone-id=1";
924 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
925 EXPECT_EQ(403U, g_test->get_resp_code());
926
927 rest_req = "/admin/log?type=data&unlock&id=1&locker-id=ceph&zone-id=1";
928 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
929 EXPECT_EQ(403U, g_test->get_resp_code());
930
931 ASSERT_EQ(0, user_rm(uid, display_name));
932 }
933
934 TEST(TestRGWAdmin, datalog_trim) {
935 string start_time,
936 end_time;
937 const char *cname = "datalog",
938 *perm = "*";
939 string rest_req;
940 unsigned shard_id = get_datalog_shard_id(TEST_BUCKET_NAME, g_ceph_context->_conf->rgw_data_log_num_shards);
941 stringstream ss;
942 list<rgw_data_change> entries;
943
944 ASSERT_EQ(get_formatted_time(start_time), 0);
945 ASSERT_EQ(0, user_create(uid, display_name));
946 ASSERT_EQ(0, caps_add(cname, perm));
947
948 rest_req = "/admin/log?type=data";
949 g_test->send_request(string("DELETE"), rest_req);
950 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
951
952 ss.str("");
953 ss << "/admin/log?type=data&start-time=" << start_time;
954 rest_req = ss.str();
955 g_test->send_request(string("DELETE"), rest_req);
956 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
957
958 ss.str("");
959 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time;
960 rest_req = ss.str();
961 g_test->send_request(string("DELETE"), rest_req);
962 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
963
964 ASSERT_EQ(0, create_bucket());
965
966 char *bucket_obj = (char *)calloc(1, TEST_BUCKET_OBJECT_SIZE);
967 ASSERT_TRUE(bucket_obj != NULL);
968 EXPECT_EQ(put_bucket_obj(TEST_BUCKET_OBJECT, bucket_obj, TEST_BUCKET_OBJECT_SIZE), 0);
969 ASSERT_EQ(0, delete_obj(TEST_BUCKET_OBJECT));
970 sleep(1);
971 EXPECT_EQ(put_bucket_obj(TEST_BUCKET_OBJECT, bucket_obj, TEST_BUCKET_OBJECT_SIZE), 0);
972 ASSERT_EQ(0, delete_obj(TEST_BUCKET_OBJECT));
973 sleep(20);
974 free(bucket_obj);
975
976 ASSERT_EQ(get_formatted_time(end_time), 0);
977 ss.str("");
978 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time
979 << "&end-time=" << end_time;
980 rest_req = ss.str();
981 g_test->send_request(string("GET"), rest_req);
982 EXPECT_EQ(200U, g_test->get_resp_code());
983 entries.clear();
984 get_datalog_list(entries);
985 EXPECT_TRUE(!entries.empty());
986
987 ss.str("");
988 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time
989 << "&end-time=" << end_time;
990 rest_req = ss.str();
991 g_test->send_request(string("DELETE"), rest_req);
992 EXPECT_EQ(200U, g_test->get_resp_code());
993
994 ss.str("");
995 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time
996 << "&end-time=" << end_time;
997 rest_req = ss.str();
998 g_test->send_request(string("GET"), rest_req);
999 EXPECT_EQ(200U, g_test->get_resp_code());
1000 entries.clear();
1001 get_datalog_list(entries);
1002 EXPECT_TRUE(entries.empty());
1003
1004 ASSERT_EQ(0, caps_rm(cname, perm));
1005 perm = "write";
1006 ASSERT_EQ(0, caps_add(cname, perm));
1007 ss.str("");
1008 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time
1009 << "&end-time=" << end_time;
1010 rest_req = ss.str();
1011 g_test->send_request(string("DELETE"), rest_req);
1012 EXPECT_EQ(200U, g_test->get_resp_code());
1013
1014 ASSERT_EQ(0, caps_rm(cname, perm));
1015 perm = "";
1016 ASSERT_EQ(0, caps_add(cname, perm));
1017 ss.str("");
1018 ss << "/admin/log?type=data&id=" << shard_id << "&start-time=" << start_time
1019 << "&end-time=" << end_time;
1020 rest_req = ss.str();
1021 g_test->send_request(string("DELETE"), rest_req);
1022 EXPECT_EQ(403U, g_test->get_resp_code());
1023
1024 ASSERT_EQ(0, delete_bucket());
1025 ASSERT_EQ(0, user_rm(uid, display_name));
1026 }
1027
1028 TEST(TestRGWAdmin, mdlog_list) {
1029 string start_time,
1030 end_time,
1031 start_time_2;
1032 const char *cname = "mdlog",
1033 *perm = "*";
1034 string rest_req;
1035 unsigned shard_id = get_mdlog_shard_id(uid, g_ceph_context->_conf->rgw_md_log_max_shards);
1036 stringstream ss;
1037
1038 sleep(2);
1039 ASSERT_EQ(get_formatted_time(start_time), 0);
1040 ASSERT_EQ(0, user_create(uid, display_name));
1041 ASSERT_EQ(0, caps_add(cname, perm));
1042
1043 rest_req = "/admin/log?type=metadata";
1044 g_test->send_request(string("GET"), rest_req);
1045 EXPECT_EQ(200U, g_test->get_resp_code());
1046 JSONParser parser;
1047 int num_objects;
1048 EXPECT_EQ (parse_json_resp(parser), 0);
1049 JSONDecoder::decode_json("num_objects", num_objects, (JSONObj *)&parser);
1050 ASSERT_EQ(num_objects,g_ceph_context->_conf->rgw_md_log_max_shards);
1051
1052 ss.str("");
1053 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time;
1054 rest_req = ss.str();
1055 g_test->send_request(string("GET"), rest_req);
1056 EXPECT_EQ(200U, g_test->get_resp_code());
1057
1058 list<cls_log_entry_json> entries;
1059 EXPECT_EQ(get_log_list(entries), 0);
1060 EXPECT_EQ(entries.size(), 4U);
1061
1062 if(entries.size() == 4) {
1063 list<cls_log_entry_json>::iterator it = entries.begin();
1064 EXPECT_TRUE(it->section.compare("user") == 0);
1065 EXPECT_TRUE(it->name.compare(uid) == 0);
1066 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_WRITE);
1067 ++it;
1068 EXPECT_TRUE(it->section.compare("user") == 0);
1069 EXPECT_TRUE(it->name.compare(uid) == 0);
1070 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_COMPLETE);
1071 ++it;
1072 EXPECT_TRUE(it->section.compare("user") == 0);
1073 EXPECT_TRUE(it->name.compare(uid) == 0);
1074 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_WRITE);
1075 ++it;
1076 EXPECT_TRUE(it->section.compare("user") == 0);
1077 EXPECT_TRUE(it->name.compare(uid) == 0);
1078 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_COMPLETE);
1079 }
1080
1081 sleep(1); /*To get a modified time*/
1082 ASSERT_EQ(get_formatted_time(start_time_2), 0);
1083 ASSERT_EQ(0, caps_rm(cname, perm));
1084 perm="read";
1085 ASSERT_EQ(0, caps_add(cname, perm));
1086 ss.str("");
1087 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time_2;
1088 rest_req = ss.str();
1089 g_test->send_request(string("GET"), rest_req);
1090 EXPECT_EQ(200U, g_test->get_resp_code());
1091
1092 entries.clear();
1093 EXPECT_EQ(get_log_list(entries), 0);
1094 EXPECT_EQ(entries.size(), 4U);
1095
1096 if(entries.size() == 4) {
1097 list<cls_log_entry_json>::iterator it = entries.begin();
1098 EXPECT_TRUE(it->section.compare("user") == 0);
1099 EXPECT_TRUE(it->name.compare(uid) == 0);
1100 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_WRITE);
1101 ++it;
1102 EXPECT_TRUE(it->section.compare("user") == 0);
1103 EXPECT_TRUE(it->name.compare(uid) == 0);
1104 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_COMPLETE);
1105 ++it;
1106 EXPECT_TRUE(it->section.compare("user") == 0);
1107 EXPECT_TRUE(it->name.compare(uid) == 0);
1108 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_WRITE);
1109 ++it;
1110 EXPECT_TRUE(it->section.compare("user") == 0);
1111 EXPECT_TRUE(it->name.compare(uid) == 0);
1112 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_COMPLETE);
1113 }
1114
1115 sleep(1);
1116 ASSERT_EQ(get_formatted_time(start_time_2), 0);
1117 ASSERT_EQ(0, user_rm(uid, display_name));
1118
1119 ASSERT_EQ(0, user_create(uid, display_name));
1120 perm = "*";
1121 ASSERT_EQ(0, caps_add(cname, perm));
1122
1123 ss.str("");
1124 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time_2;
1125 rest_req = ss.str();
1126 g_test->send_request(string("GET"), rest_req);
1127 EXPECT_EQ(200U, g_test->get_resp_code());
1128
1129 entries.clear();
1130 EXPECT_EQ(get_log_list(entries), 0);
1131 EXPECT_EQ(entries.size(), 6U);
1132 if(entries.size() == 6) {
1133 list<cls_log_entry_json>::iterator it = entries.begin();
1134 EXPECT_TRUE(it->section.compare("user") == 0);
1135 EXPECT_TRUE(it->name.compare(uid) == 0);
1136 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_REMOVE);
1137 ++it;
1138 EXPECT_TRUE(it->section.compare("user") == 0);
1139 EXPECT_TRUE(it->name.compare(uid) == 0);
1140 ++it;
1141 EXPECT_TRUE(it->section.compare("user") == 0);
1142 EXPECT_TRUE(it->name.compare(uid) == 0);
1143 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_WRITE);
1144 ++it;
1145 EXPECT_TRUE(it->section.compare("user") == 0);
1146 EXPECT_TRUE(it->name.compare(uid) == 0);
1147 EXPECT_TRUE(it->log_data.status == MDLOG_STATUS_COMPLETE);
1148 }
1149
1150 sleep(1);
1151 ASSERT_EQ(get_formatted_time(end_time), 0);
1152 ss.str("");
1153 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time
1154 << "&end-time=" << end_time;
1155 rest_req = ss.str();
1156 g_test->send_request(string("GET"), rest_req);
1157 EXPECT_EQ(200U, g_test->get_resp_code());
1158 entries.clear();
1159 EXPECT_EQ(get_log_list(entries), 0);
1160 EXPECT_EQ(entries.size(), 14U);
1161
1162 ss.str("");
1163 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time
1164 << "&max-entries=" << 1;
1165 rest_req = ss.str();
1166 g_test->send_request(string("GET"), rest_req);
1167 EXPECT_EQ(200U, g_test->get_resp_code());
1168 entries.clear();
1169 EXPECT_EQ(get_log_list(entries), 0);
1170 EXPECT_EQ(entries.size(), 1U);
1171
1172 ss.str("");
1173 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time
1174 << "&max-entries=" << 6;
1175 rest_req = ss.str();
1176 g_test->send_request(string("GET"), rest_req);
1177 EXPECT_EQ(200U, g_test->get_resp_code());
1178 entries.clear();
1179 EXPECT_EQ(get_log_list(entries), 0);
1180 EXPECT_EQ(entries.size(), 6U);
1181
1182 ASSERT_EQ(0, caps_rm(cname, perm));
1183 ss.str("");
1184 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time;
1185 rest_req = ss.str();
1186 g_test->send_request(string("GET"), rest_req);
1187 EXPECT_EQ(403U, g_test->get_resp_code());
1188
1189 /*cleanup*/
1190 ASSERT_EQ(0, caps_add(cname, perm));
1191 sleep(1);
1192 ASSERT_EQ(get_formatted_time(end_time), 0);
1193 ss.str("");
1194 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time
1195 << "&end-time=" << end_time;
1196 rest_req = ss.str();
1197 g_test->send_request(string("DELETE"), rest_req);
1198 EXPECT_EQ(200U, g_test->get_resp_code());
1199
1200 ASSERT_EQ(0, user_rm(uid, display_name));
1201 }
1202
1203 TEST(TestRGWAdmin, mdlog_trim) {
1204 string start_time,
1205 end_time;
1206 const char *cname = "mdlog",
1207 *perm = "*";
1208 string rest_req;
1209 list<cls_log_entry_json> entries;
1210 unsigned shard_id = get_mdlog_shard_id(uid, g_ceph_context->_conf->rgw_md_log_max_shards);
1211 ostringstream ss;
1212
1213 sleep(1);
1214 ASSERT_EQ(get_formatted_time(start_time), 0);
1215 ASSERT_EQ(0, user_create(uid, display_name));
1216 ASSERT_EQ(0, caps_add(cname, perm));
1217
1218 ss.str("");
1219 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time;
1220 rest_req = ss.str();
1221 g_test->send_request(string("DELETE"), rest_req);
1222 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1223
1224 g_test->send_request(string("GET"), rest_req);
1225 EXPECT_EQ(200U, g_test->get_resp_code());
1226 EXPECT_EQ(get_log_list(entries), 0);
1227 EXPECT_EQ(entries.size(), 4U);
1228
1229 sleep(1);
1230 ASSERT_EQ(get_formatted_time(end_time), 0);
1231 ss.str("");
1232 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time << "&end-time=" << end_time;
1233 rest_req = ss.str();
1234 g_test->send_request(string("DELETE"), rest_req);
1235 EXPECT_EQ(200U, g_test->get_resp_code());
1236
1237 ss.str("");
1238 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time;
1239 rest_req = ss.str();
1240 g_test->send_request(string("GET"), rest_req);
1241 EXPECT_EQ(200U, g_test->get_resp_code());
1242 entries.clear();
1243 EXPECT_EQ(get_log_list(entries), 0);
1244 EXPECT_EQ(entries.size(), 0U);
1245
1246 ASSERT_EQ(0, caps_rm(cname, perm));
1247 perm="write";
1248 ASSERT_EQ(0, caps_add(cname, perm));
1249 ASSERT_EQ(get_formatted_time(end_time), 0);
1250 ss.str("");
1251 ss << "/admin/log?type=metadata&id=" << shard_id << "&start-time=" << start_time << "&end-time=" << end_time;
1252 rest_req = ss.str();
1253 g_test->send_request(string("DELETE"), rest_req);
1254 EXPECT_EQ(200U, g_test->get_resp_code());
1255
1256 ASSERT_EQ(0, caps_rm(cname, perm));
1257 g_test->send_request(string("DELETE"), rest_req);
1258 EXPECT_EQ(403U, g_test->get_resp_code());
1259 ASSERT_EQ(0, user_rm(uid, display_name));
1260 }
1261
1262 TEST(TestRGWAdmin, mdlog_lock_unlock) {
1263 const char *cname = "mdlog",
1264 *perm = "*";
1265 string rest_req;
1266
1267 ASSERT_EQ(0, user_create(uid, display_name));
1268 ASSERT_EQ(0, caps_add(cname, perm));
1269
1270 rest_req = "/admin/log?type=metadata&lock&length=3&locker-id=ceph&zone-id=1";
1271 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1272 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1273
1274 rest_req = "/admin/log?type=metadata&lock&id=3&locker-id=ceph&zone-id=1";
1275 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1276 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1277
1278 rest_req = "/admin/log?type=metadata&lock&length=3&id=1&zone-id=1";
1279 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1280 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1281
1282 rest_req = "/admin/log?type=metadata&lock&id=3&locker-id=ceph&length=1";
1283 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1284 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1285
1286 rest_req = "/admin/log?type=metadata&unlock&id=1&zone-id=1";
1287 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1288 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1289
1290 rest_req = "/admin/log?type=metadata&unlock&locker-id=ceph&zone-id=1";
1291 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1292 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1293
1294 rest_req = "/admin/log?type=metadata&unlock&locker-id=ceph&id=1";
1295 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1296 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1297
1298 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph&zone-id=1";
1299 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1300 EXPECT_EQ(200U, g_test->get_resp_code());
1301
1302 rest_req = "/admin/log?type=metadata&unlock&id=1&locker-id=ceph&zone-id=1";
1303 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1304 EXPECT_EQ(200U, g_test->get_resp_code());
1305
1306 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph1&zone-id=1";
1307 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1308 EXPECT_EQ(200U, g_test->get_resp_code());
1309
1310 rest_req = "/admin/log?type=metadata&unlock&id=1&locker-id=ceph1&zone-id=1";
1311 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1312 EXPECT_EQ(200U, g_test->get_resp_code());
1313
1314 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph&zone-id=1";
1315 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1316 EXPECT_EQ(200U, g_test->get_resp_code());
1317 utime_t sleep_time(3, 0);
1318
1319 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph1&zone-id=1";
1320 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1321 EXPECT_EQ(500U, g_test->get_resp_code());
1322
1323 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph&zone-id=2";
1324 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1325 EXPECT_EQ(500U, g_test->get_resp_code());
1326
1327 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph&zone-id=1";
1328 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1329 EXPECT_EQ(200U, g_test->get_resp_code());
1330 sleep_time.sleep();
1331
1332 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph1&zone-id=1";
1333 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1334 EXPECT_EQ(200U, g_test->get_resp_code());
1335
1336 rest_req = "/admin/log?type=metadata&unlock&id=1&locker-id=ceph1&zone-id=1";
1337 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1338 EXPECT_EQ(200U, g_test->get_resp_code());
1339
1340 ASSERT_EQ(0, caps_rm(cname, perm));
1341 perm = "read";
1342 ASSERT_EQ(0, caps_add(cname, perm));
1343 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph&zone-id=1";
1344 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1345 EXPECT_EQ(403U, g_test->get_resp_code());
1346
1347 rest_req = "/admin/log?type=metadata&unlock&id=1&locker-id=ceph&zone-id=1";
1348 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1349 EXPECT_EQ(403U, g_test->get_resp_code());
1350
1351 ASSERT_EQ(0, caps_rm(cname, perm));
1352 perm = "write";
1353 ASSERT_EQ(0, caps_add(cname, perm));
1354 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph&zone-id=1";
1355 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1356 EXPECT_EQ(200U, g_test->get_resp_code());
1357
1358 rest_req = "/admin/log?type=metadata&unlock&id=1&locker-id=ceph&zone-id=1";
1359 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1360 EXPECT_EQ(200U, g_test->get_resp_code());
1361
1362 ASSERT_EQ(0, caps_rm(cname, perm));
1363 rest_req = "/admin/log?type=metadata&lock&id=1&length=3&locker-id=ceph&zone-id=1";
1364 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1365 EXPECT_EQ(403U, g_test->get_resp_code());
1366
1367 rest_req = "/admin/log?type=metadata&unlock&id=1&locker-id=ceph&zone-id=1";
1368 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
1369 EXPECT_EQ(403U, g_test->get_resp_code());
1370
1371 ASSERT_EQ(0, user_rm(uid, display_name));
1372 }
1373
1374 TEST(TestRGWAdmin, bilog_list) {
1375 const char *cname = "bilog",
1376 *perm = "*";
1377 string rest_req;
1378
1379 ASSERT_EQ(0, user_create(uid, display_name));
1380 ASSERT_EQ(0, caps_add(cname, perm));
1381
1382 ASSERT_EQ(0, create_bucket());
1383
1384 char *bucket_obj = (char *)calloc(1, TEST_BUCKET_OBJECT_SIZE);
1385 ASSERT_TRUE(bucket_obj != NULL);
1386 EXPECT_EQ(put_bucket_obj(TEST_BUCKET_OBJECT, bucket_obj, TEST_BUCKET_OBJECT_SIZE), 0);
1387 free(bucket_obj);
1388
1389 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1390 g_test->send_request(string("GET"), rest_req);
1391 EXPECT_EQ(200U, g_test->get_resp_code());
1392 list<cls_bilog_entry> entries;
1393 get_bilog_list(entries);
1394 EXPECT_EQ(2U, entries.size());
1395 if (entries.size() == 2) {
1396 list<cls_bilog_entry>::iterator it = entries.begin();
1397 EXPECT_EQ(it->op.compare("write"), 0);
1398 EXPECT_EQ(it->object.compare(TEST_BUCKET_OBJECT), 0);
1399 EXPECT_EQ(it->status.compare("pending"), 0);
1400 EXPECT_EQ(it->index_ver, 1U);
1401 ++it;
1402 EXPECT_EQ(it->op.compare("write"), 0);
1403 EXPECT_EQ(it->object.compare(TEST_BUCKET_OBJECT), 0);
1404 EXPECT_EQ(it->status.compare("complete"), 0);
1405 EXPECT_EQ(it->index_ver, 2U);
1406 }
1407 EXPECT_EQ(read_bucket_obj(TEST_BUCKET_OBJECT), 0);
1408 g_test->send_request(string("GET"), rest_req);
1409 EXPECT_EQ(200U, g_test->get_resp_code());
1410 entries.clear();
1411 get_bilog_list(entries);
1412 EXPECT_EQ(2U, entries.size());
1413
1414 bucket_obj = (char *)calloc(1, TEST_BUCKET_OBJECT_SIZE);
1415 ASSERT_TRUE(bucket_obj != NULL);
1416 EXPECT_EQ(put_bucket_obj(TEST_BUCKET_OBJECT_1, bucket_obj, TEST_BUCKET_OBJECT_SIZE), 0);
1417 free(bucket_obj);
1418
1419 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1420 g_test->send_request(string("GET"), rest_req);
1421 EXPECT_EQ(200U, g_test->get_resp_code());
1422 entries.clear();
1423 get_bilog_list(entries);
1424 EXPECT_EQ(4U, entries.size());
1425 if (entries.size() == 4) {
1426 list<cls_bilog_entry>::iterator it = entries.begin();
1427
1428 ++it; ++it;
1429 EXPECT_EQ(it->op.compare("write"), 0);
1430 EXPECT_EQ(it->object.compare(TEST_BUCKET_OBJECT_1), 0);
1431 EXPECT_EQ(it->status.compare("pending"), 0);
1432 EXPECT_EQ(it->index_ver, 3U);
1433 ++it;
1434 EXPECT_EQ(it->op.compare("write"), 0);
1435 EXPECT_EQ(it->object.compare(TEST_BUCKET_OBJECT_1), 0);
1436 EXPECT_EQ(it->status.compare("complete"), 0);
1437 EXPECT_EQ(it->index_ver, 4U);
1438 }
1439
1440 ASSERT_EQ(0, delete_obj(TEST_BUCKET_OBJECT));
1441 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1442 g_test->send_request(string("GET"), rest_req);
1443 EXPECT_EQ(200U, g_test->get_resp_code());
1444 entries.clear();
1445 get_bilog_list(entries);
1446
1447 EXPECT_EQ(6U, entries.size());
1448 string marker;
1449 if (entries.size() == 6) {
1450 list<cls_bilog_entry>::iterator it = entries.begin();
1451
1452 ++it; ++it; ++it; ++it;
1453 marker = it->op_id;
1454 EXPECT_EQ(it->op.compare("del"), 0);
1455 EXPECT_EQ(it->object.compare(TEST_BUCKET_OBJECT), 0);
1456 EXPECT_EQ(it->status.compare("pending"), 0);
1457 EXPECT_EQ(it->index_ver, 5U);
1458 ++it;
1459 EXPECT_EQ(it->op.compare("del"), 0);
1460 EXPECT_EQ(it->object.compare(TEST_BUCKET_OBJECT), 0);
1461 EXPECT_EQ(it->status.compare("complete"), 0);
1462 EXPECT_EQ(it->index_ver, 6U);
1463 }
1464
1465 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1466 rest_req.append("&marker=");
1467 rest_req.append(marker);
1468 g_test->send_request(string("GET"), rest_req);
1469 EXPECT_EQ(200U, g_test->get_resp_code());
1470 entries.clear();
1471 get_bilog_list(entries);
1472 EXPECT_EQ(2U, entries.size());
1473 if (entries.size() == 2U) {
1474 list<cls_bilog_entry>::iterator it = entries.begin();
1475 EXPECT_EQ(it->index_ver, 5U);
1476 ++it;
1477 EXPECT_EQ(it->index_ver, 6U);
1478 EXPECT_EQ(it->op.compare("del"), 0);
1479 }
1480
1481 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1482 rest_req.append("&marker=");
1483 rest_req.append(marker);
1484 rest_req.append("&max-entries=1");
1485 g_test->send_request(string("GET"), rest_req);
1486 EXPECT_EQ(200U, g_test->get_resp_code());
1487 entries.clear();
1488 get_bilog_list(entries);
1489 EXPECT_EQ(1U, entries.size());
1490 EXPECT_EQ((entries.begin())->index_ver, 5U);
1491
1492 ASSERT_EQ(0, caps_rm(cname, perm));
1493 perm = "read";
1494 ASSERT_EQ(0, caps_add(cname, perm));
1495 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1496 g_test->send_request(string("GET"), rest_req);
1497 EXPECT_EQ(200U, g_test->get_resp_code());
1498
1499 ASSERT_EQ(0, caps_rm(cname, perm));
1500 perm = "write";
1501 ASSERT_EQ(0, caps_add(cname, perm));
1502 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1503 g_test->send_request(string("GET"), rest_req);
1504 EXPECT_EQ(403U, g_test->get_resp_code());
1505
1506 ASSERT_EQ(0, delete_obj(TEST_BUCKET_OBJECT_1));
1507 ASSERT_EQ(0, delete_bucket());
1508 ASSERT_EQ(0, user_rm(uid, display_name));
1509 }
1510
1511 TEST(TestRGWAdmin, bilog_trim) {
1512 const char *cname = "bilog",
1513 *perm = "*";
1514 string rest_req, start_marker, end_marker;
1515
1516 ASSERT_EQ(0, user_create(uid, display_name));
1517 ASSERT_EQ(0, caps_add(cname, perm));
1518
1519 ASSERT_EQ(0, create_bucket());
1520
1521 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1522 g_test->send_request(string("DELETE"), rest_req);
1523 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
1524
1525 char *bucket_obj = (char *)calloc(1, TEST_BUCKET_OBJECT_SIZE);
1526 ASSERT_TRUE(bucket_obj != NULL);
1527 EXPECT_EQ(put_bucket_obj(TEST_BUCKET_OBJECT, bucket_obj, TEST_BUCKET_OBJECT_SIZE), 0);
1528 free(bucket_obj);
1529
1530 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1531 g_test->send_request(string("GET"), rest_req);
1532 EXPECT_EQ(200U, g_test->get_resp_code());
1533 list<cls_bilog_entry> entries;
1534 get_bilog_list(entries);
1535 EXPECT_EQ(2U, entries.size());
1536
1537 list<cls_bilog_entry>::iterator it = entries.begin();
1538 start_marker = it->op_id;
1539 ++it;
1540 end_marker = it->op_id;
1541
1542 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1543 rest_req.append("&start-marker=");
1544 rest_req.append(start_marker);
1545 rest_req.append("&end-marker=");
1546 rest_req.append(end_marker);
1547 g_test->send_request(string("DELETE"), rest_req);
1548 EXPECT_EQ(200U, g_test->get_resp_code());
1549
1550 rest_req = "/admin/log?type=bucket-index&bucket=" TEST_BUCKET_NAME;
1551 g_test->send_request(string("GET"), rest_req);
1552 EXPECT_EQ(200U, g_test->get_resp_code());
1553 entries.clear();
1554 get_bilog_list(entries);
1555 EXPECT_EQ(0U, entries.size());
1556
1557 ASSERT_EQ(0, delete_obj(TEST_BUCKET_OBJECT));
1558 ASSERT_EQ(0, delete_bucket());
1559 ASSERT_EQ(0, user_rm(uid, display_name));
1560 }
1561
1562 int main(int argc, char *argv[]){
1563 vector<const char*> args;
1564 argv_to_vec(argc, (const char **)argv, args);
1565
1566 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
1567 CODE_ENVIRONMENT_UTILITY,
1568 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
1569 common_init_finish(g_ceph_context);
1570 g_test = new admin_log::test_helper();
1571 finisher = new Finisher(g_ceph_context);
1572 #ifdef GTEST
1573 ::testing::InitGoogleTest(&argc, argv);
1574 #endif
1575 finisher->start();
1576
1577 if(g_test->extract_input(argc, argv) < 0){
1578 print_usage(argv[0]);
1579 return -1;
1580 }
1581 #ifdef GTEST
1582 int r = RUN_ALL_TESTS();
1583 if (r >= 0) {
1584 cout << "There are no failures in the test case\n";
1585 } else {
1586 cout << "There are some failures\n";
1587 }
1588 #endif
1589 finisher->stop();
1590 return 0;
1591 }