云计算自动化运维——SaltStack接口salt-api

一、salt-api简介

官方文档
SaltStack官方提供有REST API格式的salt-api项目,将使salt与第三方系统集成变得更加简单。
 salt-api有两种方式,一种是函数的形式,有定义好的函数,可以直接调用,直接写Python代码调用函数或者类就可以了。

第二种形式是salt-api有封装好的http协议,需要启动一个服务端,直接启动salt-api就可以通过http协议进行调用。

二、salt-api安装配置

实验

在salt-master端:
1、安装salt-api

yum  install salt-api -y

在这里插入图片描述
2、自签名证书,生产环境可以购买(说明:如果没有salt-call命令,装上salt-minion即可,依赖于该包)

salt-call --local tls.create_self_signed_cert

在这里插入图片描述
3、打开include加载子配置文件,方便管理,需手动添加

vim /etc/salt/master
1233 default_include: master.d/*.conf

在这里插入图片描述
4、生成自签名证书(用于ssl)

 cd  /etc/pki/tls/certs
 make testcert

在这里插入图片描述
5、此时已经生成证书localhost.crt和密钥localhost.key
在这里插入图片描述
6、配置api配置文件,将上面生成的证书写到配置文件

vim /etc/salt/master.d/api.conf
rest_cherrypy:
  port: 8000
  ssl_crt: /etc/pki/tls/certs/localhost.crt
  ssl_key: /etc/pki/tls/private/localhost.key

在这里插入图片描述
7、创建认证用户,并设置密码

useradd -M -s /sbin/nologin saltapi
echo 'saltapi' | passwd --stdin saltapi

在这里插入图片描述
8、创建认证配置文件

vim /etc/salt/master.d/auth.conf
external_auth:
  pam:
    saltapi:  #saltapi用户可使用以下模块
      - .*
      - '@wheel'
      - '@runner'
      - '@jobs'

在这里插入图片描述
9、重启salt-master和启动salt-api

systemctl restart salt-master
systemctl start salt-api

在这里插入图片描述
10、查看服务开启端口8000

netstat -antuple | grep 8000

在这里插入图片描述
11、验证login登录,获取token字符串

curl -sSk https://localhost:8000/login \
> -H 'Accept: application/x-yaml' \
> -d username=saltapi \
> -d password=saltapi \
> -d eauth=pam
return:
- eauth: pam
  expire: 1576716959.032581
  perms:
  - .*
  - '@wheel'
  - '@runner'
  - '@jobs'
  start: 1576673759.032578
  token: 696da3d2ed5ca00b6cd81d94c5960e6420530ffd
  user: saltapi

在这里插入图片描述
12、通过api执行test.ping测试连通性

curl -sSk https://172.25.1.1:8000 \
> -H 'Accept: application/x-yaml' \
> -H 'X-Auth-Token:696da3d2ed5ca00b6cd81d94c5960e6420530ffd' \
> -d client=local \
> -d tgt='*' \
> -d fun=test.ping
return:
- server4: true

在这里插入图片描述

总结

salt-api必须使用https,生产环境建议使用可信证书
当salt-api服务重启后原token失效

三、编写python脚本请求salt-api接口

自定义一个类,首先初始化时候获得token,然后使用token认证去请求相应的json文件。
salt命令在shell中使用方式是salt 客户端 方法 参数(例子:salt ‘client1’ cmd.run ‘free -m’)。
这里salt命令方法我们已经封装好了,想使用salt的什么方法就传入对应的客户端、方法、参数即可。
代码如下:

python编写异步请求模块

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'junxi'


import requests
import json
try:
    import cookielib
except:
    import http.cookiejar as cookielib

# 使用urllib2请求https出错,做的设置
import ssl
context = ssl._create_unverified_context()

# 使用requests请求https出现警告,做的设置
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


salt_api = "https://172.25.1.1:8000/"


class SaltApi:
    """
    定义salt api接口的类
    初始化获得token
    """
    def __init__(self, url):
        self.url = url
        self.username = "saltapi"
        self.password = "saltapi"
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
            "Content-type": "application/json"
            # "Content-type": "application/x-yaml"
        }
        self.params = {'client': 'local', 'fun': '', 'tgt': ''}
        # self.params = {'client': 'local', 'fun': '', 'tgt': '', 'arg': ''}
        self.login_url = salt_api + "login"
        self.login_params = {'username': self.username, 'password': self.password, 'eauth': 'pam'}
        self.token = self.get_data(self.login_url, self.login_params)['token']
        self.headers['X-Auth-Token'] = self.token

    def get_data(self, url, params):
        send_data = json.dumps(params)
        request = requests.post(url, data=send_data, headers=self.headers, verify=False)
        # response = request.text
        # response = eval(response)     使用x-yaml格式时使用这个命令把回应的内容转换成字典
        # print response
        # print request
        # print type(request)
        response = request.json()
        result = dict(response)
        # print result
        return result['return'][0]

    def salt_command(self, tgt, method, arg=None):
        """远程执行命令,相当于salt 'client1' cmd.run 'free -m'"""
        if arg:
            params = {'client': 'local', 'fun': method, 'tgt': tgt, 'arg': arg}
        else:
            params = {'client': 'local', 'fun': method, 'tgt': tgt}
        print '命令参数: ', params
        result = self.get_data(self.url, params)
        return result

def main():
    print '=================='
    print '同步执行命令'
    salt = SaltApi(salt_api)
    print salt.token
    salt_client = '*'
    salt_test = 'test.ping'
    salt_method = 'cmd.run'
    salt_params = 'free -m'
    # print salt.salt_command(salt_client, salt_method, salt_params)
    # 下面只是为了打印结果好看点
    result1 = salt.salt_command(salt_client, salt_test)
    for i in result1.keys():
        print i, ': ', result1[i]
    result2 = salt.salt_command(salt_client, salt_method, salt_params)
    for i in result2.keys():
        print i
        print result2[i]
        print

if __name__ == '__main__':
    main()

结果:
第一行是请求认证的token。
从结果可以看出来我们请求了两条命令,test.ping和free -m
在这里插入图片描述

Saltstack异步执行命令

salt执行命令有时候会有超时的问题,就是命令下发下去了,部分主机没有返回信息,这时候就很难判断命令或任务是否执行成功。因此,salt提供异步执行的功能,发出命令后立即返回一个jid。然后我们就可以根据这个jid来查询任务是否执行成功。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__author__ = 'junxi'


import requests
import json
try:
    import cookielib
except:
    import http.cookiejar as cookielib

# 使用urllib2请求https出错,做的设置
import ssl
context = ssl._create_unverified_context()

# 使用requests请求https出现警告,做的设置
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


salt_api = "https://172.25.1.1:8000/"


class SaltApi:
    """
    定义salt api接口的类
    初始化获得token
    """
    def __init__(self, url):
        self.url = url
        self.username = "saltapi"
        self.password = "saltapi"
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
            "Content-type": "application/json"
            # "Content-type": "application/x-yaml"
        }
        self.params = {'client': 'local', 'fun': '', 'tgt': ''}
        # self.params = {'client': 'local', 'fun': '', 'tgt': '', 'arg': ''}
        self.login_url = salt_api + "login"
        self.login_params = {'username': self.username, 'password': self.password, 'eauth': 'pam'}
        self.token = self.get_data(self.login_url, self.login_params)['token']
        self.headers['X-Auth-Token'] = self.token
   
    def get_data(self, url, params):
        send_data = json.dumps(params)
        request = requests.post(url, data=send_data, headers=self.headers, verify=False)
        # response = request.text
        # response = eval(response)     使用x-yaml格式时使用这个命令把回应的内容转换成字典
        # print response
        # print request
        # print type(request)
        response = request.json()
        result = dict(response)
        # print result
        return result['return'][0]

    def salt_async_command(self, tgt, method, arg=None):  # 异步执行salt命令,根据jid查看执行结果
#    """远程异步执行命令"""
        if arg:
           params = {'client': 'local_async', 'fun': method, 'tgt': tgt, 'arg': arg}
        else:
           params = {'client': 'local_async', 'fun': method, 'tgt': tgt}
        jid = self.get_data(self.url, params)['jid']
        return jid

    def look_jid(self, jid):  # 根据异步执行命令返回的jid查看事件结果
        params = {'client': 'runner', 'fun': 'jobs.lookup_jid', 'jid': jid}
        print params
        result = self.get_data(self.url, params)
        return result

def main():
    print
    print '=================='
    print '异步执行命令'
    salt1 = SaltApi(salt_api)
    salt_client = '*'
    salt_test = 'test.ping'
    salt_method = 'cmd.run'
    salt_params = 'df -hT'
    # 下面只是为了打印结果好看点
    jid1 = salt1.salt_async_command(salt_client, salt_test)
    result1 = salt1.look_jid(jid1)
    for i in result1.keys():
        print i, ': ', result1[i]

    jid2 = salt1.salt_async_command(salt_client, salt_method, salt_params)
    result2 = salt1.look_jid(jid2)
    for i in result2.keys():
        print i
        print result2[i]
        print


if __name__ == '__main__':
    main()

执行结果:
在这里插入图片描述

发布了170 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/CapejasmineY/article/details/103603361
今日推荐