• salt-api 使用(福利版)


    写在前面的话:

      salt-api是一个基于Cherrypy(python的一个web框架)的Rest API程序。

      注意:CherryPy版本3.2.5到3.7.x有一个已知的SSL追溯请使用3.2.3版本或最新的10.x版本。

    一、salt认证

    依赖:

      salt-api依赖的模块是Cherrypy,用于支持websockets的ws4py python模块(可选)

    安装及配置:

      salt-api 运行在Salt Master程序的机器上。

      1. 安装salt-api,需要确保salt-api 与salt版本一致。

      2. 安装Cherrypy,ws4py(可选)。

      3. 生成自签名证书(可选)。建议使用安全的HTTPS连接,因为salt eauth 身份验证凭证将通过线路发送。

          ①.安装 pyOpenSSL 包。

          ②.使用create_self_signed_cert() 执行功能生成自签名证书。

    salt-call --local tls.create_self_signed_cert
    

      4. 编辑配置文件添加至少一个外部认证用户或组。详情这里

      5. salt-master配置文件添加如下配置来启用rest_cherrypy模块。

    rest_cherrypy:
      port: 8000
      ssl_crt: /etc/pki/tls/certs/localhost.crt
      ssl_key: /etc/pki/tls/certs/localhost.key
    

      6. 重启salt-master 进程。

      7. 重启salt-api 进程。

    二、使用

    开始使用之路吧。

      首先是服务端认证,通过每个请求传递会话令牌来执行身份验证,token通过Login URL生成。

    token认证采用两种方法发送:一种是hearder头添加认证token,另一种作为会话cookie。

    用法:

      请求主体必须是一组命令。使用此工作流程来构建命令:

        1. 选择一个客户端界面。

        2. 选择一个功能。

        3.填写所选客户端所需的其余参数。

    client字段是对Salt的python api中使用的主要python类的引用。

      local:向本地发送命令的“本地”使用。等同于salt 命令。

      runner:调用master的runner 模块。等同于salt-run命令。

      wheel:调用master的wheel模块。wheel没有知己额的CLI命令,它通常广利Master-side资源,例如状态文件,支柱文件,salt配置文件,以及salt-key类似的功能。

    在执行LocalClient,它需要将命令转发给Minions,所以需要tgt参数来指定minionid.

               也需要arg(数组)和kwarg(之前)参数,这些值被发送到minions并用作请求函数的参数。

    RunnerClient和WheelClient直接在Master上执行,因此不需要接受这些参数。

    header头设置

      REST接口在接受什么样的数据格式以及它将返回什么格式(例如,JSON,YAML,urlencoded)方面是灵活的

        通过包含Content-type头来指定请求正文中的数据格式。

        使用Accept头指定相应主体所需的数据格式。

    关于CherryPy的并发

      CherryPy服务器是一个生成就绪的线程HTTP服务器,用Python编写。它使用线程池来处理HTTP请求,所以不适合维护大量的并发同步连接,在配置默认设置的中等硬件上,他最高大约30到50个并发连接。

      注意:每个salt的命令运行都会启动一个实例化的进程(LocalClient),它将自己的监听器实例化为salt事件总线,并发出自己的周期性salturil.find_job查询来确定Minion是否仍在运行该命令,不完全是一个轻量级操作。

    超时

      CherryPy还可以设置HTTP超时时间。LocalClient和RunnerClient都可以在顶级关键字(timeout)中设置自己的超时参数。

    异步操作

      由于性能开销和HTTP超时,长时间运行上述操作,可以使用local_asyn,runner_asyn,wheel_asyn进行异步方式运行更能节省开销。执行结果可以通过 /jobs/<jid> URL 从缓存中获取,也可以使用salt的Rerutner 系统收集到数据存储中。

      /events URL专门用户处理长时间运行的HTTP请求,并包含了作业返回的salt事件总线,但该操作具有不同步性。

    性能调整

      设置thread_pool和socket_queue_size 可以用来增加处理传入请求的rest_cherrypy的能力。设置这些配置时需要留意RAM的使用情况以及可用文件句柄。由于salt-api是基于salt使用,同时还需要考虑salt的性能。

    下面福利时间:

      下面的代码大概整合了一些经常使用的api,送给大家。

        未完待续。。。

      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 __author__ = '40kuai'
      4 __version__ = 'v0.0.1'
      5 """
      6 1. 整合 salt-api 功能
      7 2. 获取token多次使用,发现token过期后重新获取token从当前失败任务重新继续执行
      8 3. 可选:出现接口或服务异常(501),本次操作尝试几次重新执行
      9 arg 为模块需要传入的参数,kwargs为pillar或grains参数。
     10 
     11 分为以下几个类:
     12     1. salt-api 方法类
     13     2. 发送请求的类
     14 """
     15 
     16 from urlparse import urljoin
     17 import requests
     18 
     19 
     20 class Salt_Api():
     21     def __init__(self, url, username, password):
     22         self.url = url
     23         self._username = username
     24         self._password = password
     25         self.get_token()
     26 
     27     def get_token(self, eauth='pam', ):
     28         """获取salt-api使用的token"""
     29         get_token_url = urljoin(self.url, 'login')
     30         json_data = {'username': self._username, 'password': self._password, 'eauth': eauth}
     31         token_obj = requests.post(get_token_url, json=json_data, verify=False)
     32         if token_obj.status_code != 200:
     33             raise Exception(token_obj.status_code)
     34         self.token = token_obj.json()['return'][0]['token']
     35 
     36     def post(self, prefix='/', json_data=None, headers=None):
     37         post_url = urljoin(self.url, prefix)
     38         if headers is None:
     39             headers = {'X-Auth-Token': self.token, 'Accept': 'application/json'}
     40         else:
     41             headers = {'X-Auth-Token': self.token, }.update(headers)
     42         post_requests = requests.post(post_url, json=json_data, headers=headers, verify=False)
     43         return post_requests.json()
     44 
     45     def get(self, prefix='/', json_data=None, headers=None):
     46         post_url = urljoin(self.url, prefix)
     47         if headers is None:
     48             headers = {'X-Auth-Token': self.token, 'Accept': 'application/json'}
     49         else:
     50             headers = {'X-Auth-Token': self.token, }.update(headers)
     51         get_requests = requests.get(post_url, json=json_data, headers=headers, verify=False)
     52         return get_requests.json()
     53 
     54     def get_all_key(self):
     55         """获取所有minion的key"""
     56         json_data = {'client': 'wheel', 'fun': 'key.list_all'}
     57         content = self.post(json_data=json_data)
     58         minions = content['return'][0]['data']['return']['minions']
     59         minions_pre = content['return'][0]['data']['return']['minions_pre']
     60         return minions, minions_pre
     61 
     62     def accept_key(self, minion_id):
     63         """认证minion_id,返回Ture or False"""
     64         json_data = {'client': 'wheel', 'fun': 'key.accept', 'match': minion_id}
     65         content = self.post(json_data=json_data)
     66         return content['return'][0]['data']['success']
     67 
     68     def delete_key(self, node_name):
     69         """删除minion_id,返回Ture or False"""
     70         json_data = {'client': 'wheel', 'fun': 'key.delete', 'match': node_name}
     71         content = self.post(json_data=json_data)
     72         return content['return'][0]['data']['success']
     73 
     74     def host_remote_module(self, tgt, fun, arg=None):
     75         """根据主机执行函数或模块,模块的参数为arg"""
     76         json_data = {'client': 'local', 'tgt': tgt, 'fun': fun, }
     77         if arg:
     78             json_data.update({'arg': arg})
     79         content = self.post(json_data=json_data)
     80         return content['return']
     81 
     82     def group_remote_module(self, tgt, fun, arg=None):
     83         """根据分组执行函数或模块,模块的参数为arg"""
     84         json_data = {'client': 'local', 'tgt': tgt, 'fun': fun, 'expr_form': 'nodegroup'}
     85         if arg:
     86             json_data.update({'arg': arg})
     87         content = self.post(json_data=json_data)
     88         return content['return']
     89 
     90     def host_sls_async(self, tgt, arg):
     91         '''主机异步sls '''
     92         json_data = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg}
     93         content = self.post(json_data=json_data)
     94         return content['return']
     95 
     96     def group_sls_async(self, tgt, arg):
     97         '''分组异步sls '''
     98         json_data = {'client': 'local_async', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup'}
     99         content = self.post(json_data=json_data)
    100         return content['return']
    101 
    102     def server_hosts_pillar(self, tgt, arg, **kwargs):
    103         '''针对主机执行sls and pillar '''
    104         print kwargs
    105         kwargs = {'pillar': kwargs['kwargs']}
    106         json_data = {"client": "local", "tgt": tgt, "fun": "state.sls", "arg": arg, "kwarg": kwargs}
    107         content = self.post(json_data=json_data)
    108         return content['return']
    109 
    110     def server_group_pillar(self, tgt, arg, **kwargs):
    111         '''分组进行sls and pillar'''
    112         kwargs = {'pillar': kwargs['kwargs']}
    113         json_data = {'client': 'local', 'tgt': tgt, 'fun': 'state.sls', 'arg': arg, 'expr_form': 'nodegroup',
    114                      'kwarg': kwargs}
    115         content = self.post(json_data=json_data)
    116         return content['return']
    117 
    118     def jobs_all_list(self):
    119         '''打印所有jid缓存'''
    120         json_data = {"client": "runner", "fun": "jobs.list_jobs"}
    121         content = self.post(json_data=json_data)
    122         return content['return']
    123 
    124     def jobs_jid_status(self, jid):
    125         '''查看jid运行状态'''
    126         json_data = {"client": "runner", "fun": "jobs.lookup_jid", "jid": jid}
    127         content = self.post(json_data=json_data)
    128         return content['return']
    129 
    130     def keys_minion(self, hostname):
    131         """Show the list of minion keys or detail on a specific key"""
    132         content = self.get('keys/%s' % hostname)
    133         return content
    134 
    135 
    136 if __name__ == '__main__':
    137     url = 'https://local:8000/'
    138     obj = Salt_Api(url, 'username', 'password')
    139     print obj.keys_minion('minionid')
    salt-api
  • 相关阅读:
    剑指Offer-Python(6-10)
    Python对MySQL进行增删查改
    剑指Offer-Python(1-5)
    转载:Python中collections模块
    读取单词文件并查某个单词出现的次数
    Python正则表达式-换行的匹配
    Python爬虫-换行的匹配
    转载:Pycharm的常用快捷键
    Python 正则表达式
    Python的类与对象
  • 原文地址:https://www.cnblogs.com/40kuai/p/9164994.html
Copyright © 2020-2023  润新知