天天看点

深入理解ceph-disk activate 源码逻辑

文章目录

  • ​​CEPH-DISK代码逻辑​​
  • ​​`Activate osd`的主要逻辑如下​​
  • ​​DEF main_activate激活osd的入口函数​​
  • ​​DEF mount_activate挂载临时目录,分配osd id并初始化osd​​
  • ​​DEF activate 分配osd_id以及初始化osd​​

CEPH-DISK代码逻辑

#对activate子命令进行解析,并设置参数的函数属性为main_activate
make_activate_parser(subparsers)      

​Activate osd​

​的主要逻辑如下

  1. 将已经prepare且格式化好的磁盘第一分区挂载到临时目录 ,默认为​

    ​/var/lib/ceph/tmp/mnt.xxx​

  2. 根据​

    ​/var/lib/ceph/tmp/​

    ​​文件夹下磁盘sdx的​

    ​osd-lockbox.sdx​

    ​所在行号分配该磁盘的osd id编号
  3. 初始化osd

    a. 将osd加入到monmap中,使用命令​​

    ​ceph --cluster ceph --name client.bootstrap-osd --keyring keyring mon getmap -o monmap​

    ​​ b. 初始化osd id的集群属性以及用户组,包括​

    ​ceph-osd --cluster ceph --mkfs -i osd_id --monmap monmap --osd-data path --osd-uuid fsid --seruer ceph --setgroup ceph​

  4. 挂载osd对应id的目录​

    ​/var/lib/ceph/osd/{cluster}-{osd_id}​

  5. 启动osd进程​

    ​systemctl start ceph-osd@id​

DEF main_activate激活osd的入口函数

def main_activate(args):
    ...
    #获取到要激活的设备路径
     dev = str(args.path)[5:]
    dev = dev[:-1]
    osd_prepare_lock = ("%s.%s" %(OSD_PREPARE, dev))
    ...
    #该函数功能主要是以上描述中的激活osd的前三步
     (cluster, osd_id) = mount_activate(
     dev=args.path,
     activate_key_template=args.activate_key_template,
     init=args.mark_init,
     dmcrypt=args.dmcrypt,
     dmcrypt_key_dir=args.dmcrypt_key_dir,
     reactivate=args.reactivate,
     )
     ...
     #启动osd进程
     if (not args.no_start_daemon and
        args.mark_init not in (None, 'none')):
    start_daemon(
        cluster=cluster,
        osd_id=osd_id,
    )      
DEF mount_activate挂载临时目录,分配osd id并初始化osd
def mount_activate(
    dev,
    activate_key_template,
    init,
    dmcrypt,
    dmcrypt_key_dir,
    reactivate=False,
):
    ...
    #使用ceph-conf命令从指定的ceph.conf中获取挂载属性(一般为挂载的文件系统类型)
    mount_options = get_mount_options(cluster='ceph', fs_type=fstype)
    
    #使用如上步骤中获取到的挂载属性进行挂载,将第一分区挂载到临时文件目录。
    #该挂载的目的是为了检查磁盘是否处于deactivate的状态,并查看分区所属用户组以及权限是否正确
    path = mount(dev=dev, fstype=fstype, options=mount_options)
    ...
    #调用函数activate进行osd id的分配并初始化osd
    (osd_id, cluster) = activate(path, activate_key_template, init)
    ...
    #初始化osd已经成功,卸载掉临时目录,挂载osd对应id的目录`/var/lib/ceph/osd/{cluster}-{osd_id}`
    if active:
        LOG.info('%s osd.%s already mounted in position; unmounting ours.'
                 % (cluster, osd_id))
        unmount(path)
    elif other:
        raise Error('another %s osd.%s already mounted in position '
                    '(old/different cluster instance?); unmounting ours.'
                    % (cluster, osd_id))
    else:
        move_mount(
            dev=dev,
            path=path,
            cluster=cluster,
            osd_id=osd_id,
            fstype=fstype,
            mount_options=mount_options,
        )      

DEF activate 分配osd_id以及初始化osd

def activate(
   path,
   activate_key_template,
   init,
):
   #检查当前路径是否是osd的data分区(第一分区),否则报错
   check_osd_magic(path)
   
   #从临时目录下获取从集群配置文件以及密钥文件中中获取到的集群相关属性:
   #ceph_fsid集群唯一标识
   #cluster集群名称
   #fsid bluestore唯一标识
   #keyring osd的启动密钥
    ceph_fsid = read_one_line(path, 'ceph_fsid')
   if ceph_fsid is None:
       raise Error('No cluster uuid assigned.')
   LOG.debug('Cluster uuid is %s', ceph_fsid)

   cluster = find_cluster_by_uuid(ceph_fsid)
   if cluster is None:
       raise Error('No cluster conf found in ' + SYSCONFDIR +
                   ' with fsid %s' % ceph_fsid)
   LOG.debug('Cluster name is %s', cluster)

   fsid = read_one_line(path, 'fsid')
   if fsid is None:
       raise Error('No OSD uuid assigned.')
   LOG.debug('OSD uuid is %s', fsid)

   keyring = activate_key_template.format(cluster=cluster,
                                          statedir=STATEDIR)
   #先从临时目录下/var/lib/ceph/tmp/mnt.xxx 的whoami文件中获取osd id
   osd_id = get_osd_id(path)
   #获取不到,则进行创建
   if osd_id is None:
      #创建osd_id依赖 /var/lib/ceph/tmp/osd-lockbox.sdx 
      #该文件是prepare过程中为每个磁盘分配的锁文件ceph-osd-lockbox.sdx(sdx为磁盘符号)
      #osd编号是直接从该锁文件读取得到,该文件是在prepare时创建的
       osd_id = allocate_osd_id(
           cluster=cluster,
           fsid=fsid,
           keyring=keyring,
           path=path,
       )
       write_one_line(path, 'whoami', osd_id)
   LOG.debug('OSD id is %s', osd_id)
   ...
   #通过mkfs初始化osd,设置osd在集群中的属性:
   #osd加入monmap,osd的数据分区路径,osd所在的bluestore标识,osd各个分区的用户权限以及用户组权限
   if not os.path.exists(os.path.join(path, 'ready')):
   LOG.debug('Initializing OSD...')
   # re-running mkfs is safe, so just run until it completes
   mkfs(
       path=path,
       cluster=cluster,
       osd_id=osd_id,
       fsid=fsid,
       keyring=keyring,
   )
  
   #移除初始化标记,防止其他方式需要初始化osd需要打标
   for other in INIT_SYSTEMS:
       if other != init:
           try:
               os.unlink(os.path.join(path, other))
           except OSError:
               pass
   #向文件夹中标记activate状态为ok
   if not os.path.exists(os.path.join(path, 'active')):
       write_one_line(path, 'active', 'ok')