天天看點

salt的api學習記錄---minion的啟動流程

最近在看minion的啟動的源代碼,一路曲折啊,經過一番努力,終于了解了流程。現在記錄下,友善以後查閱。

總體來說流程如下:

1、解析指令行參數和minion配置檔案,得到options和config字典

2、設定日志(salt.log.setup.setup_logfile_logger負責)

3、設定pidfile

4、根據master參數決定調用salt.minion.MultiMinion或者salt.minion.Minion初始化

5、調用tune_in方法

解析指令行參數和配置檔案調用的是salt.Minion,這個類極其複雜,使用了進階概念元類,多重繼承。我看的時候特别暈,隻是了解了大概。

對應檔案是salt/__init__.py,這個檔案中的Minion類是salt.utils.parsers.MinionOptionParser的子類。

下面代碼對應檔案是salt/utils/parsers.py。

class MinionOptionParser(MasterOptionParser):

    __metaclass__ = OptionParserMeta # 元類

    description = (
        'The Salt minion, receives commands from a remote Salt master.'
    )    

    # ConfigDirMixIn config filename attribute
    _config_filename_ = 'minion'
    # LogLevelMixIn attributes
    # LOGS_DIR = '/var/log/salt'
    _default_logging_logfile_ = os.path.join(syspaths.LOGS_DIR, 'minion')

    # 設定self.config字典的
    def setup_config(self):
        return config.minion_config(self.get_config_file_path(),
                                    minion_id=True)      

設定日志,調用的是salt.log.setup.setup_logfile_logger函數,主要是設定handler,loglevel,formatter。用到的是logging子產品。對應的檔案是salt/log/setup.py

初始化是一般調用的是salt.minion.Minion,如果設定的多個masters,則會調用salt.minion.MultiMinion。這裡以salt.minion.Minion講解過程。對應檔案是salt/minion.py

salt.minion.Minion初始化過程如下:

1、驗證ZMQ的版本

2、擷取grains

3、向ret端口發送驗證請求,擷取master的aes和pub端口

4、擷取pillar資料

5、裝載可用的minion子產品和returners

6、設定schedule

向ret端口發送驗證請求,進行數字簽名過程如下:

對應的接口是salt.crypt.Auth

1、調用get_keys方法load key,如果沒有則生成密鑰對,密鑰儲存到minion.pem,公鑰儲存到minion.pub,然後再load key,使用的子產品是M2Crypto.RSA

2、進行數字簽名,向master_ip:4506發送請求

請求格式:

payload = {

'enc':'clear',

'load':{

'cmd':'_auth',

'id':minion的id,

'pub':minion.pub的内容,

}

傳回格式:

'aes':加密的資料,

'enc':'pub',

'pub_key':key,

'publish_port':'4505',

'sig':加密的資料

3、将pub_key字段對應的資料寫入minion_master.pub

4、對aes和sig字段對應的資料解密,代碼如下

key = self.get_keys()
key_str = key.private_decrypt(payload['aes'], RSA.pkcs1_oaep_padding)
if 'sig' in payload:
    m_path = os.path.join(self.opts['pki_dir'], self.mpub)
    if os.path.exists(m_path):
        try:
            mkey = RSA.load_pub_key(m_path)
        except Exception:
            return '', ''
        digest = hashlib.sha256(key_str).hexdigest()
        m_digest = mkey.public_decrypt(payload['sig'], 5)
        if m_digest != digest:
            return '', ''
else:
    return '', ''
if '_|-' in key_str:
    return key_str.split('_|-')
else:
    if 'token' in payload:
        token = key.private_decrypt(payload['token'], RSA.pkcs1_oaep_padding)
        return key_str, token
    elif not master_pub:
        return key_str, ''      

擷取grains資料主要調用的是salt.loader.grains,這個方法會間接去調用salt.loader.Loader類,對應檔案是salt/loader.py,這個是調用imp子產品加載子產品的。

擷取pillar資料主要調用的是salt.pillar.get_pillar,對應檔案是salt/pillar/__init__.py。

後期會針對pillar和grains的擷取詳細介紹下,或者看看saltstack中國使用者組的介紹。

tune_in的這個方法屬于salt.minion.Minion的。流程如下:

1、擷取pub和pull的位址,預設是檔案,通過ipc通信

2、綁定pub和pull

3、建立sub socket連接配接master的pub位址并保持長連接配接

4、執行死循環,觸發event

這裡隻是大概的記錄下流程,寫的不怎麼詳細,還請大家海涵。

接下來的任務就是研究salt-minion去處理一個job的流程。

參考:

http://www.saltstack.cn/projects/cssug-kb/wiki/Salt-zeromq-01

繼續閱讀