目录

后端部分 Admin Socket

前端部分 python


ceph 命令下发流程:命令行/usr/bin/ceph-->python 前端部分处理-->Admin Socket后端部分处理

后端部分 Admin Socket

https://blog.csdn.net/bandaoyu/article/details/123070446

前端部分 python

从命令行到python到C语言的过程

摘抄自:https://blog.csdn.net/SY_Yu/article/details/79131881

既然讲了admin_socket的的后台部分,那前端输入命令到底是怎么去调用的后台呢,或者前台的命令到底是怎么发送的呢?平时的ceph命令到底是怎么解析的呢?

在终端敲入了ceph stastus,终端就返回了集群的状态。那在这个过程中,到底是调用了什么。

主要涉及了
ceph-12.2.2\src\ceph.in
ceph-12.2.2\src\pybind\ceph_argparse.py
ceph-12.2.2\src\pybind\rados\rados.pyx

这里的pybind目录基本ceph所有的python脚本都在该目录下。

首先ceph命令都是由/usr/bin/ceph来执行,打开该文件发现内容与ceph.in相同,即这个脚本是由源码里面的ceph.in文件生成而来。

而在ceph.in中import了rados,

import rados
···
cluster_handle = run_in_thread(rados.Rados,name=name,
    clustername=clustername,conf_defaults=conf_defaults,
    conffile=conffile)
···

json_command(cluster_handle, target=target, argdict=valid_dict,inbuf=inbuf)

json_command在src\pybind\ceph_argparse.py中定义。

def json_command(cluster,
                 target: Optional[Tuple[str, str]] = ('mon', ''),
                 prefix: Optional[str] = None,
                 argdict: Optional[Dict[str, str]] = None,
                 inbuf: Optional[bytes] = b'',
                 timeout: Optional[int] = 0,
                 verbose: Optional[bool] = False) -> Tuple[int, bytes, str]:
   ……

try:
     ……
        ret, outbuf, outs = send_command_retry(cluster,
                                               target, json.dumps(cmddict),
                                               inbuf, timeout, verbose)

def send_command_retry(*args, **kwargs):
    while True:
        try:
            return send_command(*args, **kwargs)
        except Exception as e:
            if ('get_command_descriptions' in str(e) and
                'object in state configuring' in str(e)):
                continue
            else:
                raise

def send_command(cluster, target=('mon', ''), cmd=None,
                  inbuf=b'', timeout=0,verbose=False):
···
   if len(target) < 2 or target[1] == '': 
      ret, outbuf, outs = run_in_thread(cluster.mon_command,
                                  cmd, inbuf, timeout)
   else:
      ret, outbuf, outs = run_in_thread(cluster.mon_command,
                           cmd, inbuf, timeout, target[1])
···

调用了src\pybind\rados\rados.pyx的rados类中的mon_command():cluster.mon_command

cdef class Rados(object):
    """This class wraps librados functions"""
    # NOTE(sileht): attributes declared in .pyd

def __init__(self, *args, **kwargs):
        PyEval_InitThreads()
           self.__setup(*args, **kwargs)
    def mon_command(self, cmd, inbuf, timeout=0, 
                    target=None):
    ···

def mon_command(self, cmd, inbuf, timeout=0, target=None):
    ……
    try:
            if target:
                 with nogil:
                      ret =rados_mon_command_target(self.cluster,
                       _target,<const char **>_cmd,
                       _cmdlen,<const char*>_inbuf,
                       _inbuf_len,&_outbuf, &_outbuf_len,
                       &_outs, &_outs_len)
            else:
                 with nogil:
                      ret = rados_mon_command(self.cluster,
                          <const char **>_cmd, _cmdlen,
                          <const char*>_inbuf, _inbuf_len,
                          &_outbuf, &_outbuf_len,&_outs,
                          &_outs_len)
    ……

根据src\pybind\rados\rados.pyx文件中

cdef extern from "rados/librados.h" nogil:
····
int rados_mon_command(rados_t cluster, const char **cmd,
                     size_t cmdlen,const char *inbuf, 
                     size_t inbuflen,char **outbuf, 
                     size_t *outbuflen,char **outs, 
                     size_t *outslen)
···

千辛万苦到了ceph的C++代码部分啦

这波骚操作令人窒息。笔者作为小菜鸡,第一次看通的时候也是长舒了一口气。

下面是常规操作。

librados.h

extern "C" int rados_mon_command(rados_t cluster, 
                            const char **cmd,size_t cmdlen,
                            const char *inbuf, 
                            size_t inbuflen,char **outbuf,
                            size_t *outbuflen,char **outs,
                            size_t *outslen)
{

tracepoint(librados, rados_mon_command_enter, cluster, cmdlen, inbuf, inbuflen);
  librados::RadosClient *client = (librados::RadosClient*)cluster;
  bufferlist inbl;
  bufferlist outbl;
  string outstring;
  vector<string> cmdvec;

for (size_t i = 0; i < cmdlen; i++) {
    tracepoint(librados, rados_mon_command_cmd, cmd[i]);
    cmdvec.push_back(cmd[i]);
  }

inbl.append(inbuf, inbuflen);
  int ret = client->mon_command(cmdvec, inbl, &outbl, &outstring);

do_out_buffer(outbl, outbuf, outbuflen);
  do_out_buffer(outstring, outs, outslen);
  tracepoint(librados, rados_mon_command_exit, ret, outbuf, 
              outbuflen, outs, outslen);
  return ret;
}

在最新版本中mgr负责了一些诸如ceph osd df命令的解析。mgr承担了一部分原本由monitor来完成的事情
在下面的函数里也进行了对命令的处理

实例演示

摘抄自https://blog.51cto.com/u_15127692/3915231

ceph -s是如何与ceph cluster进行交互的呢?

发送端:

命令行敲入ceph -s,执行/usr/bin/ceph, 传入参数-s

 从该文件起初的导入部分可以得知:

 由send_command()去与ceph cluster通信:

def send_command(cluster, target=('mon', ''), cmd=None, inbuf='', timeout=0,
                 verbose=False):
    """  注释部分:使用librados的mon_command/osd_command/pg_command给daemon发送指令
    Send a command to a daemon using librados's
    mon_command, osd_command, or pg_command.  Any bulk input data
    comes in inbuf.

Returns (ret, outbuf, outs); ret is the return code, outbuf is
    the outbl "bulk useful output" buffer, and outs is any status
    or error message (intended for stderr).

If target is osd.N, send command to that osd (except for pgid cmds)
    """
    cmd = cmd or []
    try: #target[0] 用以区分发送的目标类型,mon、osd、pg、mds的
        if target[0] == 'osd':
            osdid = target[1]

if verbose:
                print >> sys.stderr, 'submit {0} to osd.{1}'.\
                    format(cmd, osdid)
            ret, outbuf, outs = \
                cluster.osd_command(osdid, cmd, inbuf, timeout)  #osd中消息发送主体

elif target[0] == 'pg':
            pgid = target[1]
            # pgid will already be in the command for the pg <pgid>
            # form, but for tell <pgid>, we need to put it in
            if cmd:
                cmddict = json.loads(cmd[0])
                cmddict['pgid'] = pgid
            else:
                cmddict = dict(pgid=pgid)
            cmd = [json.dumps(cmddict)]
            if verbose:
                print >> sys.stderr, 'submit {0} for pgid {1}'.\
                    format(cmd, pgid)
            ret, outbuf, outs = \
                cluster.pg_command(pgid, cmd, inbuf, timeout)

elif target[0] == 'mon':
            if verbose:
                print >> sys.stderr, '{0} to {1}'.\
                    format(cmd, target[0])
            if target[1] == '':
                ret, outbuf, outs = cluster.mon_command(cmd, inbuf, timeout)
            else:
                ret, outbuf, outs = cluster.mon_command(cmd, inbuf, timeout, target[1])
        elif target[0] == 'mds':
            mds_spec = target[1]

if verbose:
                print >> sys.stderr, 'submit {0} to mds.{1}'.\
                    format(cmd, mds_spec)

try:
                from cephfs import LibCephFS
            except ImportError:
                raise RuntimeError("CephFS unavailable, have you installed libcephfs?")

filesystem = LibCephFS(cluster.conf_defaults, cluster.conffile)
            filesystem.conf_parse_argv(cluster.parsed_args)

filesystem.init()
            ret, outbuf, outs = \
                filesystem.mds_command(mds_spec, cmd, inbuf)
            filesystem.shutdown()
        else:
            raise ArgumentValid("Bad target type '{0}'".format(target[0]))

except Exception as e:
        if not isinstance(e, ArgumentError):
            raise RuntimeError('"{0}": exception {1}'.format(cmd, e))
        else:
            raise

return ret, outbuf, outs

此时以给mon的指令为例,继续分析:

python 的 mon_command 里调用python 的  rados_mon_command_target()

python 的rados_mon_command_target()里调用 C++的client->mon_command,client为librados::RadosClient;

librados的client的mon_command()调用里调用start_mon_command

继续MonClient的start_mon_command():

之后调用MonClient::_send_command()里面继续_send_mon_message(m),然后调用底层封装的socket发送消息;

接收端:

接来下来从mon端(即server端)入手,从接收到消息,解包开始:消息的tag为:MSG_MON_COMMAND,消息主体是一个结构体MMonCommand

从mon/Monitor.cc中的handle_command函数入手,查询ceph cluster状态 get_cluster_status()函数:

继续跟get_cluster_status()函数:

【ceph】ceph命令处理流程代码分析(终端敲命令之后发生的事)相关推荐

  1. quagga 命令定义的代码分析--从定义到实现

    本文大多数内容转自http://blog.chinaunix.net/uid-20788636-id-1841428.html,部分内容自己读过代码之后觉得需要多加注意的,也记录下来 在quagga中 ...

  2. 【鸿蒙OS开发入门】06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 启动init进程

    [鸿蒙OS开发入门]06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 一.head.S 启动start_kernel() 1.1 start_kernel() ...

  3. 【鸿蒙OS开发入门】13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解

    [鸿蒙OS开发入门]13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解 一. /etc/init.cfg 系统默认cfg:启动lo回环网卡 1.1 init.Hi35 ...

  4. 【Android SDM660源码分析】- 02 - UEFI XBL QcomChargerApp充电流程代码分析

    [Android SDM660源码分析]- 02 - UEFI XBL QcomChargerApp充电流程代码分析 一.加载 UEFI 默认应用程序 1.1 LaunchDefaultBDSApps ...

  5. USB NCM usbnet 枚举流程代码分析

    USB NCM usbnet 枚举流程代码分析 一.cdc_ncm.c 1.1 [id_table]struct usb_device_id结构体 1.1.1 match_flags 设备类型 1.1 ...

  6. MSM USB插入流程代码分析

    点击打开链接 代码路径:kernel\msm-3.18\drivers\power\qpnp-smbcharger.c src_detect_handler -->update_usb_stat ...

  7. PCIe学习笔记之pcie初始化枚举和资源分配流程代码分析

    本文主要是对PCIe的初始化枚举.资源分配流程进行分析.代码对应的是linux 4.19, 平台是arm64. 文章首发于这里 1. PCIe architecture 1.1 pcie的拓扑结构 在 ...

  8. git 提交代码命令_提交代码:git push 命令的四种形式

    Git是一种分布式版本控制系统,可以高效地处理项目的版本管理.若对Git的基本使用还不太了解,可以先看一下下面的文章. Git 常用命令 使用Git的工作流程:修改.暂存.提交.推送 Git操作:在多 ...

  9. 命令模式 Java代码演示【使用命令模式实现播放器功能】

    文章目录 模式介绍 模式的结构与实现 命令模式扩展(实现播放器功能) 模式介绍 命令(Command)模式的定义如下:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开.这样俩者之前通过 ...

最新文章

  1. oracle批量更新数据从另一表_常用SQL系列之(五):多表和禁止插入、批量与特殊更新等...
  2. [译] 你不需要基于 CSS Grid 的栅格布局系统
  3. golang的定时器NewTimer、NewTicker使用
  4. Winform中实现文件另存为后并打开文件
  5. 使用汇编软件emu8086输出十次Hello World!
  6. 官方的正则表达式组件 RegularExpressions (4) : 表达式选项
  7. Java Throwable toString()方法与示例
  8. 数据结构之基于Java的顺序列表实现
  9. 某学校买了一批计算机配置为,初中信息技术考试选择题
  10. Android MediaCodec 解码H264/H265码流视频
  11. Macbook reset PRAM
  12. 怎么做有内容的二维码?二维码在线制作教程
  13. pymongo的简单使用
  14. 计算机教室架构,物联网智慧教室架构
  15. 在IDEA开发一个自动输入法切换插件
  16. python+adb命令实现自动刷视频脚本
  17. RGB和HSV相互转换
  18. VS Code 2022路线图:大量Spring Boot优化提上日程
  19. 量化投资:为什么在中国发展之路任重而道远
  20. 10-集合(核心类库)

热门文章

  1. qq私聊顺序回复_QQ更新!这些新功能,一个比一个好用
  2. qq邮箱中的链接点不开
  3. 小游戏开发周期多长时间
  4. 220v怎样转12v输出
  5. 洛谷大佬的题解 p1427小鱼倒数字
  6. win10 问题及优化 ssd
  7. Go语言正/反向代理的姿势
  8. [ps文字特效] ps水晶字体
  9. Chapter 3 Phenomenon——4
  10. 【JVM】VM是什么?JVM是什么?JVM作用是什么?JVM特点?JVM位置?JVM组成?