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