RGW User信息是如何保存在RADOS中的
rgw支持使用uid、access key和email来标记一个User,这些数据最终都会保存在default.rgw.meta
数据池中。我们通过librados中的接口来读出用户数据,并解析成 RGWUserInfo
,以此来熟悉librados接口,为后续rgw开发工作做准备(熟悉代码啊)~
分析
在default.rgw.meta
中,存在如下命名空间:
- users.uid
- users.keys
- users.email
我们使用如下命令创建一个user:
./bin/radosgw-admin user create --uid=hello --display-name=Hello --email=hello@gmail.com --access-key=accesskey --secret-key =secretkey
查看meta数据池中各个命名空间的对象:
$ ./bin/rados ls -p default.rgw.meta --all
users.email hello@gmail.com
users.keys accesskey
users.uid hello
$ ./bin/rados stat -p default.rgw.meta -N users.email hello@gmail.com
default.rgw.meta/hello@gmail.com mtime 2022-08-04 19:30:26.000000, size 9
$ ./bin/rados stat -p default.rgw.meta -N users.keys accesskey
default.rgw.meta/accesskey mtime 2022-08-04 19:30:26.000000, size 9
$ ./bin/rados stat -p default.rgw.meta -N users.uid hello
default.rgw.meta/hello mtime 2022-08-04 19:30:26.000000, size 268
直接说结论,rgw中,使用email和accesskey获取到uid,在通过uid获取RGWUserInfo
。
接下来,我们将通过代码来获取这些信息~
code
test case 1: 通过email 获取uid
TEST(RGW_RADOS_USER, USERS_EMAIL) {
librados::Rados rados;
EXPECT_EQ(rados.init2("client.admin", "ceph", 0), 0);
EXPECT_EQ(rados.conf_read_file("/XXXXXX/ceph/build/ceph.conf"), 0);
EXPECT_EQ(rados.connect(), 0);
librados::IoCtx ioctx;
EXPECT_EQ(rados.ioctx_create("default.rgw.meta", ioctx), 0);
//设置namespace
ioctx.set_namespace("users.email");
// int operate(const std::string& oid, ObjectReadOperation *op, bufferlist *pbl);
bufferlist bl;
librados::ObjectReadOperation op;
uint64_t size = 0;
struct timespec ts{};
//获取对象大小及创建时间
op.stat2(&size, &ts, nullptr);
EXPECT_EQ(size, 0);
//不太清楚出参bufferlist的作用
EXPECT_EQ(ioctx.operate("hello@gmail.com", &op, &bl), 0);
librados::ObjectReadOperation rop;
bufferlist bl1;
rop.read(0, size, &bl1, nullptr);
//不太清楚出参bufferlist的作用
EXPECT_EQ(ioctx.operate("hello@gmail.com", &rop, &bl), 0);
//最终落盘的userid时 RGWUID 不是 rgw_user
RGWUID user;
bufferlist::const_iterator bliter = bl1.cbegin();
user.decode(bliter);
EXPECT_EQ("hello", user.user_id.id);
rados.shutdown();
}
通过ObjectReadOperation
读取一个对象内容比较麻烦,要先通过stat获取其size,然后再read。
使用access key获取uid基本相同,只要将 namespace 更改为users.keys 并将object name 更改为 accesskey 即可。
test case 2:通过uid获取用户详细信息(RGWUserInfo)
#include <iostream>
#include "include/rados/librados.hpp"
#include <gtest/gtest.h>
#include "rgw/rgw_basic_types.h"
#include "rgw/rgw_user.h"
#include "rgw/rgw_common.h"
using namespace std;
TEST(RGW_RADOS_USER, USERS_INFO) {
librados::Rados rados;
EXPECT_EQ(rados.init2("client.admin", "ceph", 0), 0);
EXPECT_EQ(rados.conf_read_file("/XXXXXX/ceph/build/ceph.conf"), 0);
EXPECT_EQ(rados.connect(), 0);
librados::IoCtx ioctx;
EXPECT_EQ(rados.ioctx_create("default.rgw.meta", ioctx), 0);
ioctx.set_namespace("users.uid");
bufferlist bl;
librados::ObjectReadOperation op;
uint64_t size = 0;
struct timespec ts{};
op.stat2(&size, &ts, nullptr);
EXPECT_EQ(size, 0);
EXPECT_EQ(ioctx.operate("hello", &op, &bl), 0);
librados::ObjectReadOperation rop;
bufferlist bl1;
rop.read(0, size, &bl1, nullptr);
EXPECT_EQ(ioctx.operate("hello", &rop, &bl), 0);
RGWUID uid;
RGWUserInfo user_info;
bufferlist::const_iterator bliter = bl1.cbegin();
uid.decode(bliter);
user_info.decode(bliter);
EXPECT_EQ(uid.user_id, user_info.user_id);
EXPECT_EQ("hello", user_info.user_id.id);
EXPECT_EQ("accesskey", user_info.access_keys.begin()->first);
EXPECT_EQ("hello@gmail.com", user_info.user_email);
rados.shutdown();
}
meta:users.uid:uid对象保存的数据为 RGWUID
+RGWUserInfo
~