librados是ceph各组件对外暴露的模块,藉由librados接口,可以高效的使用ceph内的组件进行CRUD等操作。
1 2 3 4 5
| import rados cluster = rados.Rados(conffile = 'ceph.conf', conf = dict (keyring = '/path/to/keyring')) cluster.connect() cmd = json.dumps({"prefix": "osd safe-to-destroy", "ids": ["2"], "format": "json"}) c.mon_command(cmd, b'')
|
这里的conf=keyring主要用于当打开了cephx等认证措施时,ceph.conf中又没有记录认证所用到的keyring文件路径时,进行额外设置使用。
最近我在参照python的librados使用,调用C的接口时,就一直遇到cephx认证打开之后,无法成功rados_connect
的情况,具体原理还得细看,但应该和cephx及这个keyring存在强相关性是可以确认的了。
连接成功之后,主要使用下属这几个接口来查询pool
,osd
,pg
等一些信息。
1 2 3 4
| Rados.mon_command(self, cmd, inbuf, timeout=0, target=None) Rados.osd_command(self, osdid, cmd, inbuf, timeout=0) Rados.mgr_command(self, cmd, inbuf, timeout=0, target=None) Rados.pg_command(self, pgid, cmd, inbuf, timeout=0)
|
就目前而言,我在抓取IO等指标时,用的比较多的接口是mon_command
和mgr_command
,使用这几个接口能进行的操作,都有提供cli和rest接口。我主要是在使用cli熟悉接口之后,会去代码中的MonCommands.h
和MgrCommands.h
文件中去找相近的prefix,然后参照着使用。
但是偶尔也是会遇到像ceph osd pool stats
和ceph pg ls-by-pools
这类没怎么能找到相关prefix的情况。这个时候可以充分利用起ceph这个cli入口其实是个python文本的功能了。
python -m pgd /bin/ceph osd pool stats
执行,在new_style_command
函数内的json_command
处打断点,进入后,打印cmddict
就可以看到cli发送出去的prefix拼接出来是什么样子的了,然后再拿着这个去代码里搜就好了。
开发者模式[^2]
make vstart
async模式
- mon_command_async
- 好像RadosClient.cc里有这个异步下发任务, 但是似乎并没有对外提供成librados的接口.
- 之后有空应该是可以利用这个封装出来使用的应该.
radosstripper理解
rados连接过程
似乎有加载client name.
parse_config_files似乎还有指定不读取任何配置文件的时候, 即便是默认配置文件
- global_pre_init里调用的似乎就是这个.
"cdef class Rados(object):"->"name = 'client.admin'"
context 是什么?
rados_create2
librados::RadosClient::connect理解
源码
- RadosClient
- IoctxImpl
- AioCompletionImpl
- osdc
超时参数
- client_mount_timeout
- rados_osd_op_timeout
- rados_mon_op_timeout
pacafic版本, 实际超时退出时间为client_mount_timeout的10倍
3c2b30e这次提交, get_monmap_and_config
中重构成10次retry, 而这个函数之前就是在oneshot monmap fdde016
中引入的monclient过程中get_monmap_and_config以及设置10倍的interval, 之前12版本不存在该项, 所以不会10倍超时.
这个提交13版本就开始有了.
这条commit关联的pr中有144条commit, 该条commit也说了只是解决了问题, 所以设计初衷并不算很清晰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| int MonClient::get_monmap_and_config() { ldout(cct, 10) << __func__ << dendl; ceph_assert(!messenger);
int tries = 10;
cct->init_crypto(); auto shutdown_crypto = make_scope_guard([this] { cct->shutdown_crypto(); });
int r = build_initial_monmap(); if (r < 0) { lderr(cct) << __func__ << " cannot identify monitors to contact" << dendl; return r; }
messenger = Messenger::create_client_messenger( cct, "temp_mon_client"); ceph_assert(messenger); messenger->add_dispatcher_head(this); messenger->start(); auto shutdown_msgr = make_scope_guard([this] { messenger->shutdown(); messenger->wait(); delete messenger; messenger = nullptr; if (!monmap.fsid.is_zero()) { cct->_conf.set_val("fsid", stringify(monmap.fsid)); } });
want_bootstrap_config = true; auto shutdown_config = make_scope_guard([this] { std::unique_lock l(monc_lock); want_bootstrap_config = false; bootstrap_config.reset(); });
ceph::ref_t<MConfig> config; while (tries-- > 0) { r = init(); if (r < 0) { return r; } r = authenticate(cct->_conf->client_mount_timeout); if (r == -ETIMEDOUT) { shutdown(); continue; } if (r < 0) { break; } { std::unique_lock l(monc_lock); if (monmap.get_epoch() && !monmap.persistent_features.contains_all( ceph::features::mon::FEATURE_MIMIC)) { ldout(cct,10) << __func__ << " pre-mimic monitor, no config to fetch" << dendl; r = 0; break; } while ((!bootstrap_config || monmap.get_epoch() == 0) && r == 0) { ldout(cct,20) << __func__ << " waiting for monmap|config" << dendl; auto status = map_cond.wait_for(l, ceph::make_timespan( cct->_conf->mon_client_hunt_interval)); if (status == std::cv_status::timeout) { r = -ETIMEDOUT; } }
if (bootstrap_config) { ldout(cct,10) << __func__ << " success" << dendl; config = std::move(bootstrap_config); r = 0; break; } } lderr(cct) << __func__ << " failed to get config" << dendl; shutdown(); continue; }
|