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