天天看點

深入了解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')