使用python3調(diào)用 salt-api

使用python3調(diào)用 salt-api

在項(xiàng)目中我們不能使用命令行的模式去調(diào)用salt-api,所以我們可以寫一個(gè)基于salt-api的類,方便項(xiàng)目代碼的調(diào)用。在這里特別附上兩種方式實(shí)現(xiàn)的python3版本的salt-api class。

方式一

#python3.x
import pycurl
from io import BytesIO
import json

class PyCurl(object):
    def __init__(self, url, **kwargs):
        # 傳入url地址
        self.url = url
        # 取出header相關(guān)信息
        self.header = kwargs.get("header", None)
        # 創(chuàng)建一個(gè)curl對象
        self.curl = pycurl.Curl()
        # setopt 來設(shè)置一些請求選項(xiàng)
        # 指定請求的URL
        self.curl.setopt(self.curl.URL, self.url)
        # 設(shè)置代理瀏覽器
        self.curl.setopt(self.curl.HEADER, False)
        # 設(shè)置請求方式
        self.curl.setopt(self.curl.POST, True)
        # 設(shè)置https方式
        self.curl.setopt(pycurl.SSL_VERIFYPEER, 0)
        self.curl.setopt(pycurl.SSL_VERIFYHOST, 0)
        # 判斷header是否存在
        if self.header:
            # 設(shè)置模擬瀏覽器
            self.curl.setopt(self.curl.HTTPHEADER, self.header)

    def request(self, data=None, timeout=None):
        # 判斷對象類型 是否為 str
        if isinstance(data, str):
            #將數(shù)據(jù)提交
            self.curl.setopt(pycurl.POSTFIELDS, data)
        header_buf = BytesIO()
        body_buf = BytesIO()
        # 強(qiáng)制獲取新的連接,即替代緩存中的連接
        self.curl.setopt(self.curl.FRESH_CONNECT, True)
        # 完成交互后強(qiáng)制斷開連接,不重用
        self.curl.setopt(self.curl.FORBID_REUSE, True)
        if str(timeout).isdigit() and timeout > 0:
            # 設(shè)置timeout超時(shí)時(shí)間
            self.curl.setopt(self.curl.TIMEOUT, timeout)
        # 將返回的HTTP HEADER定向到回調(diào)函數(shù)header_buf
        self.curl.setopt(self.curl.HEADERFUNCTION, header_buf.write)
        # 將返回的內(nèi)容定向到回調(diào)函數(shù)body_buf
        self.curl.setopt(self.curl.WRITEFUNCTION, body_buf.write)
        try:
            # 服務(wù)器返回信息
            self.curl.perform()
        except pycurl.error:
            return False
        # 狀態(tài)碼
        http_code = self.curl.getinfo(self.curl.HTTP_CODE)
        # 關(guān)閉連接
        self.curl.close()
        # 返回狀態(tài)碼 header body
        return {"http_code": http_code, "header": header_buf.getvalue(), "body": body_buf.getvalue(), "url": self.url}


class SaltApi(object):

    def __init__(self,**kwargs):

        # 設(shè)置超時(shí)時(shí)間
        self.timeout = kwargs.get("timeout", 300)
        # 設(shè)置頭信息
        self.header = kwargs.get("header", ["Content-Type:application/json"])
        # 獲取url
        self.__url = "https://192.168.104.76:8000"

        # 獲取
        self.__username = "salt-api"
        self.__password = "salt-api"

    # token id 獲取
    def token_id(self):
        obj = {'eauth': 'pam', 'username': self.__username, 'password': self.__password}
        result = self.post(prefix="/login",**obj)
        if result:
            try:
                self.__token_id = result['return'][0]['token']
            except KeyError:
                raise KeyError
        print(self.__token_id)
        return self.__token_id

    def post(self, prefix="/",token=None,**data):

        # url拼接
        url = self.__url + prefix
        print (data)
        # 實(shí)例化
        self.header.append(str(token))
        curl = PyCurl(url, header=self.header)
        # 發(fā)起請求
        result = curl.request(data=json.dumps(data), timeout=self.timeout)
        # 判斷值
        if not result:
            return result
        #判斷狀態(tài)碼是否等于200
        if result["http_code"] != 200:
            self.response = "response code %s".format(result["info"]["http_code"])
            return self.response
        result = json.loads(result["body"].decode())
        # 判斷是否有error
        if "error" in result and result["error"]:
            self.response = "%s(%s)" % (result["error"]["data"], result["error"]["code"])
            return self.response
        #返回正確的數(shù)據(jù)
        return result

    def all_key(self):
        '''
        獲取所有的minion_key
        '''
        token = 'X-Auth-Token:%s'%self.token_id()
        obj = {'client': 'wheel', 'fun': 'key.list_all'}
        content = self.post(token=token,**obj)
        # 取出認(rèn)證已經(jīng)通過的
        minions = content['return'][0]['data']['return']['minions']
        #print('已認(rèn)證',minions)
        # 取出未通過認(rèn)證的
        minions_pre = content['return'][0]['data']['return']['minions_pre']
        # print('未認(rèn)證',minions_pre)
        return minions,minions_pre

    def accept_key(self,node_name):
        '''
        如果你想認(rèn)證某個(gè)主機(jī) 那么調(diào)用此方法
        '''
        token = 'X-Auth-Token:%s' % self.token_id()
        obj = {'client': 'wheel', 'fun': 'key.accept','match':node_name}
        content = self.post(token=token,**obj)
        print (content)
        ret = content['return'][0]['data']['success']
        return ret

    # 刪除認(rèn)證方法
    def delete_key(self, node_name):
        obj = {'client': 'wheel', 'fun': 'key.delete', 'match': node_name}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)

        ret = content['return'][0]['data']['success']
        return ret

    # 針對主機(jī)遠(yuǎn)程執(zhí)行模塊
    def host_remote_func(self, tgt, fun):
        ''' tgt是主機(jī) fun是模塊
            寫上模塊名 返回 可以用來調(diào)用基本的資產(chǎn)
            例如 curl -k https://ip地址:8080/ \
        >      -H "Accept: application/x-yaml" \
        >      -H "X-Auth-Token:b50e90485615309de0d83132cece2906f6193e43" \
        >      -d client='local' \
        >      -d tgt='*' \
        >      -d fun='test.ping'  要執(zhí)行的模塊
        return:
        - iZ28r91y66hZ: true
          node2.minion: true
        '''
        obj = {'client': 'local', 'tgt': tgt, 'fun': fun}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        ret = content['return'][0]
        return ret

    def group_remote_func(self,tgt,fun):
        obj = {'client': 'local', 'tgt': tgt, 'fun': fun,'expr_form': 'nodegroup'}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        print (content)
        ret = content['return'][0]
        return ret

    def host_remote_execution_module(self,tgt,fun,arg):
        '執(zhí)行fun 傳入傳入?yún)?shù)arg '
        obj = {'client': 'local', 'tgt': tgt, 'fun': fun,'arg': arg}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        ret = content['return'][0]
        return ret
        #print(salt_aa.host_remote_execution_module('*', 'cmd.run', 'ifconfig'))

    # 基于分組來執(zhí)行
    def group_remote_execution_module(self, tgt, fun, arg):
        '''
        根據(jù)分組來執(zhí)行
        tgt =
        '''

        obj = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg, 'expr_form': 'nodegroup'}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        jid = content['return'][0]
        return jid

    def host_sls(self, tgt, arg):
        '''主機(jī)進(jìn)行sls'''
        obj = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        return content

    def group_sls(self, tgt, arg):
        ''' 分組進(jìn)行sls '''
        obj = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        jid = content['return'][0]['jid']
        return jid

    def host_sls_async(self, tgt, arg):
        '''主機(jī)異步sls '''
        obj = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        jid = content['return'][0]['jid']
        return jid

    def group_sls_async(self, tgt, arg):
        '''分組異步sls '''
        obj = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        jid = content['return'][0]['jid']
        return jid

    def server_group_pillar(self, tgt, arg, **kwargs):
        '''分組進(jìn)行sls and pillar'''
        obj = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup',
               'kwarg': kwargs}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        jid = content['return'][0]
        print (jid)

    def server_hosts_pillar(self, tgt, arg,**kwargs):
        '''針對主機(jī)執(zhí)行sls and pillar '''
        obj = {"client": "local", "tgt": tgt, "fun": "state.sls", "arg": arg,"kwarg":kwargs}
        token = 'X-Auth-Token:%s' % self.token_id()
        content = self.post(token=token, **obj)
        jid = content['return'][0]
        return jid

    def jobs_all_list(self):
        '''打印所有jid緩存'''
        token = 'X-Auth-Token:%s' % self.token_id()
        obj = {"client": "runner", "fun": "jobs.list_jobs"}
        content = self.post(token=token, **obj)
        print (content)

    def jobs_jid_status(self, jid):
        '''查看jid運(yùn)行狀態(tài)'''
        token = 'X-Auth-Token:%s' % self.token_id()
        obj = {"client": "runner", "fun": "jobs.lookup_jid", "jid": jid}
        content = self.post(token=token, **obj)
        print (content)
        return content
if __name__ == '__main__':

    sa = saltapi.SaltApi()
    print (sa.host_remote_execution_module('node76','cmd.run','ifconfig'))
    print (sa.accept_key("node76"))
  

方式二

#python3x
import urllib,json
import urllib.request
import urllib.parse
import ssl

ssl._create_default_https_context = ssl._create_unverified_context


class SaltAPI(object):
    __token_id = ''

    def __init__(self,url,user,password):
        self.__url = url
        self.__user = user
        self.__password = password

    def token_id(self):
        """
            用戶登陸和獲取token
        :return:
        """
        params = {'eauth': 'pam', 'username': self.__user, 'password': self.__password}
        encode = urllib.parse.urlencode(params)
        obj = urllib.parse.unquote(encode).encode('utf-8')
        content = self.postRequest(obj, prefix='/login')
        try:
            self.__token_id = content['return'][0]['token']
        except KeyError:
            raise KeyError

    def postRequest(self,obj,prefix='/'):
        url = self.__url + prefix
        headers = {'X-Auth-Token': self.__token_id}
        req = urllib.request.Request(url, obj, headers)
        opener = urllib.request.urlopen(req)
        content = json.loads(opener.read().decode('utf-8'))
        return content

    def list_all_key(self):
        """
            獲取包括認(rèn)證、未認(rèn)證salt主機(jī)
        """

        params = {'client': 'wheel', 'fun': 'key.list_all'}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        minions = content['return'][0]['data']['return']['minions']
        minions_pre = content['return'][0]['data']['return']['minions_pre']
        return minions, minions_pre

    def delete_key(self, node_name):
        '''
            拒絕salt主機(jī)
        '''

        params = {'client': 'wheel', 'fun': 'key.delete', 'match': node_name}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]['data']['success']
        return ret

    def accept_key(self,node_name):
        '''
            接受salt主機(jī)
        '''

        params = {'client': 'wheel', 'fun': 'key.accept', 'match': node_name}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]['data']['success']
        return ret

    def salt_get_jid_ret(self,jid):
        """
            通過jid獲取執(zhí)行結(jié)果
        :param jid: jobid
        :return: 結(jié)果
        """
        params = {'client':'runner', 'fun':'jobs.lookup_jid', 'jid': jid}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]
        return ret

    def salt_running_jobs(self):
        """
            獲取運(yùn)行中的任務(wù)
        :return: 任務(wù)結(jié)果
        """
        params = {'client':'runner', 'fun': 'jobs.active'}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]
        return ret

    def remote_noarg_execution_sigle(self, tgt, fun):
        """
            單臺minin執(zhí)行命令沒有參數(shù)
        :param tgt: 目標(biāo)主機(jī)
        :param fun:  執(zhí)行模塊
        :return: 執(zhí)行結(jié)果
        """
        params = {'client': 'local', 'tgt': tgt, 'fun': fun}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        # print(content)
        # {'return': [{'salt-master': True}]}
        ret = content['return'][0]
        return ret

    def remote_execution_single(self, tgt, fun, arg):
        """
            單臺minion遠(yuǎn)程執(zhí)行,有參數(shù)
        :param tgt: minion
        :param fun: 模塊
        :param arg: 參數(shù)
        :return: 執(zhí)行結(jié)果
        """
        params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        # print(content)
        # {'return': [{'salt-master': 'root'}]}
        ret = content['return']
        return ret

    def remote_async_execution_module(self, tgt, fun, arg):
        """
            遠(yuǎn)程異步執(zhí)行模塊,有參數(shù)
        :param tgt: minion list
        :param fun: 模塊
        :param arg: 參數(shù)
        :return: jobid
        """
        params = {'client': 'local_async', 'tgt': tgt, 'fun': fun, 'arg': arg, 'expr_form': 'list'}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        # print(content)
        # {'return': [{'jid': '20180131173846594347', 'minions': ['salt-master', 'salt-minion']}]}
        jid = content['return'][0]['jid']
        return jid

    def remote_execution_module(self, tgt, fun, arg):
        """
            遠(yuǎn)程執(zhí)行模塊,有參數(shù)
        :param tgt: minion list
        :param fun: 模塊
        :param arg: 參數(shù)
        :return: dict, {'minion1': 'ret', 'minion2': 'ret'}
        """
        params = {'client': 'local', 'tgt': tgt, 'fun': fun, 'arg': arg, 'expr_form': 'list'}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        # print(content)
        # {'return': [{'salt-master': 'root', 'salt-minion': 'root'}]}
        ret = content['return'][0]
        return ret

    def salt_state(self, tgt, arg, expr_form):
        '''
        sls文件
        '''
        params = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': expr_form}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]
        return ret

    def salt_alive(self, tgt):
        '''
        salt主機(jī)存活檢測
        '''
        params = {'client': 'local', 'tgt': tgt, 'fun': 'test.ping'}
        obj = urllib.parse.urlencode(params).encode('utf-8')
        self.token_id()
        content = self.postRequest(obj)
        ret = content['return'][0]
        return ret


if __name__ == '__main__':
        salt = SaltAPI(url="https://192.168.104.76:8000",user="salt-api",password="salt-api")
        minions, minions_pre = salt.list_all_key()
        # 說明如果'expr_form': 'list',表示minion是以主機(jī)列表形式執(zhí)行時(shí),需要把list拼接成字符串,如下所示
        minions = ['node76', 'node76']
        hosts = map(str, minions)
        hosts = ",".join(hosts)
        ret = salt.remote_noarg_execution_sigle('node76', 'test.ping')
        print(ret)
        ret = salt.remote_noarg_execution_sigle('node76', 'test.ping')
        print(ret)
        # print(type(ret))
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容