saltstack(二)--- salt-api

salt-api有兩種,一種是封裝好的函數,直接在命令行或者python代碼中調用;第二種是封裝好的http協議的api,須要啓動一個服務端
 
如下操做均在centos7下實現,centos6不能直接引入salt
 
master端須要安裝一個包,minion端不須要安裝
 
yum install -y salt-api

 

1. 加載master配置文件(master端)python

In [1]: import salt.config

In [2]: __opts__ = salt.config.client_config('/etc/salt/master')

In [3]: __opts__['timeout']                                        
Out[3]: 5

 

2. 加載minion配置文件(minion)mysql

In [1]: import salt.config

In [2]: __opts__ = salt.config.minion_config('/etc/salt/minion')

In [3]: __opts__['id']
Out[3]: '192.168.123.107'

In [4]: __opts__['master']
Out[4]: '192.168.123.106'

 

3. master端執行模塊sql

In [4]: import salt.client    
                                    
In [5]: localclient = salt.client.LocalClient()  
                 
In [6]: localclient.cmd('*', 'test.ping')
Out[6]: {'192.168.123.107': True}

In [8]: localclient.cmd('*', 'cmd.run', ['w'])                         
Out[8]: {'192.168.123.107': ' 15:52:17 up  1:10,  2 users,  load average: 0.00, 0.01, 0.05\nUSER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT\nroot     tty1                      14:42    1:08m  0.05s  0.05s -bash\nroot     pts/0    192.168.123.34   14:45    2:01   0.42s  0.35s /usr/bin/python2 /usr/bin/ipython'}

In [9]: localclient.cmd('*', ['cmd.run', 'test.ping'], [['whoami'], []])              //一次執行多個模塊
Out[9]: {'192.168.123.107': {'cmd.run': 'root', 'test.ping': True}}

 

4. 自定義模塊vim

[root@localhost salt]# mkdir -p /srv/salt/
[root@localhost salt]# cd /srv/salt/
[root@localhost salt]# mkdir _modules           //目錄名必須爲_modules,自定義的模塊放到這個目錄下
[root@localhost salt]# cd _modules/
[root@localhost _modules]# cat jd.py           //裏面想寫什麼邏輯寫什麼邏輯
#!/usr/bin/env python

def hello(name):
    return {'name': name}

[root@localhost _modules]# salt '*' saltutil.sync_modules            //把模塊下發到minion
192.168.123.107:
    - modules.jd

[root@localhost _modules]# salt '*' jd.hello python                  //在命令行調用
192.168.123.107:
    ----------
    name:
        python

In [4]: localclient.cmd('*', 'jd.hello', ['python'])                //在api調用
Out[4]: {'192.168.123.107': {'name': 'python'}}

 

5. saltstack的異步調用centos

有時調用一個自定義模塊,這個模塊執行很長(例如編譯安裝mysql的模塊),master須要一直等待執行,這種場景適合使用異步處理
master執行一個任務,得到一個id,把id丟入消息隊列中(zeromq),隔段時間再去取
 
異步調用只能在master端上用,並且要使用runner
[root@localhost ~]# mkdir /srv/salt/_runner                           //建立runner目錄
[root@localhost ~]# cd /srv/salt/_runner/
[root@localhost _runner]# vim /etc/salt/master                        //配置文件定義目錄路徑
......
# Add any additional locations to look for master runners:
runner_dirs: ['/srv/salt/_runner']
......

[root@localhost _runner]# systemctl restart salt-master

-------------------------------------------------------------------------------->
[root@localhost _runner]# cat getresult.py
#!/usr/bin/env python

import time
import salt.config
import salt.client

def get(minion, function, params):
    __opts__ = salt.config.client_config('/etc/salt/master')
    conf_file = __opts__['conf_file']
    localclient = salt.client.LocalClient(conf_file)                       //由於minion端也有salt.client方法(並且不一樣於master的用法),若是做爲module下發到minion執行,會報錯
    jid = localclient.cmd_async(minion, function, params.split(','))
    #jid = localclient.cmd_async('*', 'cmd.run', ['df -h'])
    wait_time = 0
    sleep_interval = 1
    while wait_time < __opts__['timeout']:
        print('wait {0} seconds'.format(wait_time))
        result = localclient.get_cache_returns(jid)
        if result:
            print(type(result))
            return result
        time.sleep(sleep_interval)                                       //把任務放到隊列中,從隊列取,都須要時間,因此須要阻塞(休眠)
        wait_time += sleep_interval

----------------------------------------------------------------------------->
[root@localhost _runner]# cat /srv/salt/_modules/jd.py
#!/usr/bin/env python

def hello(name):
    return {'name': name}

--------------------------------------------------------------------------->

[root@localhost _runner]# salt-run getresult.get 192.168.123.107 jd.hello 'python'                       //在命令行調用不成功,在httpapi中能夠成功調用
wait 0 seconds
wait 1 seconds
<type 'dict'>
192.168.123.107:
    ----------
    out:
        nested
    ret:
        Passed invalid arguments to jd.hello: hello() takes exactly 1 argument (6 given)
        None

[root@localhost _runner]# salt-run getresult.get 192.168.123.107 jd.hello 'p'     
wait 0 seconds
wait 1 seconds
<type 'dict'>
192.168.123.107:
    ----------
    ret:
        ----------
        name:
            p
[root@localhost _runner]# salt-run getresult.get 192.168.123.107 jd.meminfo
wait 0 seconds
wait 1 seconds
<type 'dict'>
192.168.123.107:
    ----------
    ret:
        ----------
        MemAvailable:
            627.125M

 

若是自定義模塊不須要參數,則_runner不須要paramsapi

[root@bogon _modules]# cat jd.py
#!/usr/bin/env python

import codecs

def meminfo():
    with codecs.open('/proc/meminfo') as fd:
        for line in fd:
            if line.startswith('MemAvailable'):
                result = str(int(line.split()[1])/1024.0) + 'M'
                return {'MemAvailable': result}
[root@bogon _runner]# cat testparam.py
#!/usr/bin/env python

import time
import salt.client

def get_no_param(minion, function):
    __opts__ = salt.config.client_config('/etc/salt/master')
    conf_file = __opts__['conf_file']
    localclient = salt.client.LocalClient(conf_file)
    jid = localclient.cmd_async(minion, function)
    wait_time = 0
    sleep_interval = 1
    while wait_time < __opts__['timeout']:
        print('wait {0} seconds'.format(wait_time))
        result = localclient.get_cache_returns(jid)
        if result:
            print(type(result))
            return result
        time.sleep(sleep_interval)
        wait_time += sleep_interval

 

[root@bogon _runner]# salt-run testparam.get_no_param 192.168.0.126 jd.meminfo
192.168.0.126:
    ----------
    ret:
        ----------
        MemAvailable:
            615.9921875M

 

在api中執行salt-runbash

In [1]: import salt.config

In [2]: import salt.runner

In [3]: __opts__ = salt.config.client_config('/etc/salt/master')

In [4]: runnerclient = salt.runner.RunnerClient(__opts__)

In [20]: runnerclient.cmd('manage.status')
down:
up:
    - 192.168.123.107
Out[20]: {'down': [], 'up': ['192.168.123.107']}

In [21]: runnerclient.cmd('testparam.get_no_param', ['*', 'jd.meminfo'])
wait 0 seconds
wait 1 seconds
<type 'dict'>
192.168.123.107:
    ----------
    ret:
        ----------
        MemAvailable:
            626.6328125M
Out[21]: {'192.168.123.107': {'ret': {'MemAvailable': '626.6328125M'}}}

>>> runnerclient.cmd('testparam.get', ['*', 'jd.hello', 'aaa'])
wait 0 seconds
wait 1 seconds
<type 'dict'>
192.168.0.126:
    ----------
    ret:
        ----------
        name:
            aaa
{'192.168.0.126': {'ret': {'name': 'aaa'}}}

 

6. minion上執行salt命令異步

服務端是salt,客戶端上是salt-callasync

[root@localhost ~]# salt-call test.ping
local:
    True

 

在api裏調用函數

In [1]: import salt.client  

In [2]: caller = salt.client.Caller('/etc/salt/minion')

In [4]: caller.cmd('test.ping')
Out[4]: True

 

7. salt的內置變量__salt__

__salt__是一個字典,是salt的全局變量,不是寫模塊的時候自定義的,寫模塊的時候直接拿來就用
只要定義的模塊下發到minion,就能夠使用salt變量
 
格式:__salt__['function'](params)
用法:在一個模塊裏調用另外一個模塊
[root@localhost _modules]# cat jd.py
#!/usr/bin/env python

import codecs

def hello(name):
    return {'name': name}

def foo(name):
    return __salt__['jd.hello'](name)         //調用jd.hello函數

---------------------------------------------------------------------------->
[root@localhost _modules]# salt '*' saltutil.sync_modules
192.168.123.107:
    - modules.jd

---------------------------------------------------------------------------->
[root@localhost _modules]# salt '*' jd.foo bar
192.168.123.107:
    ----------
    name:
        bar

---------------------------------------------------------------------------->
In [24]: import salt.client

In [25]: localclient = salt.client.LocalClient()     

In [27]: localclient.cmd('*', 'jd.foo', ['bar'])
Out[27]: {'192.168.123.107': {'name': 'bar'}}
相關文章
相關標籤/搜索