使用salt-api来搭建salt自动化平台

简介:

一、介绍

    通常使用saltstack都是在master的服务器上直接命令操作,这个对于运维人员来说不是什么大事,但是也会有出错的时候,而一旦出错,就会有不可挽回的后果。

二、框架

    这里使用django框架,通过对salt-api的封装,传入命令,执行api,将结果返回到页面上显示。注意:为了防止误操作,我们对传入的命令进行了检查,所有被定义的危险命令将不会被执行。(我这里为了简单,所以定义了可以被执行的命令。),前端使用了jquery+ajax的方式来不刷新页面就将结果显示在页面上的方式。

三、salt-api的安装

    网上教程很多,我这里就不再废话了。

四、django代码

   1)、整体结构

        92d5cb02ff19097972c6a09fe3c6e7ea.png


    2)、salt_api.py(这里参照了github上dzhops的代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# -*- coding: utf-8 -*-
import  urllib2, urllib, json
import  requests
import  json
import  ssl
ssl._create_default_https_context  =  ssl._create_unverified_context
class  SaltAPI( object ):
   def  __init__( self , url, username, password):
       self .__url  =  url.rstrip( '/' )
       self .__user  =  username
       self .__password  =  password
       self .__token_id  =  self .saltLogin()
   def  saltLogin( self ):
       params  =  { 'eauth' 'pam' 'username' self .__user,  'password' self .__password}
       encode  =  urllib.urlencode(params)
       obj  =  urllib.unquote(encode)
       headers  =  { 'X-Auth-Token' : ''}
       url  =  self .__url  +  '/login'
       req  =  urllib2.Request(url, obj, headers)
       opener  =  urllib2.urlopen(req)
       content  =  json.loads(opener.read())
       try :
           token  =  content[ 'return' ][ 0 ][ 'token' ]
           return  token
       except  KeyError:
           raise  KeyError
   def  postRequest( self , obj, prefix = '/' ):
       url  =  self .__url  +  prefix
       headers  =  { 'X-Auth-Token' self .__token_id}
       req  =  urllib2.Request(url, obj, headers)
       opener  =  urllib2.urlopen(req)
       content  =  json.loads(opener.read())
       return  content
   def  masterToMinionContent( self , tgt, fun, arg):
       '''
         Master控制Minion,返回的结果是内容,不是jid;
         目标参数tgt是一个如下格式的字符串:'*' 或 'zhaogb-201'
       '''
       if  tgt  = =  '*' :
           params  =  { 'client' 'local' 'tgt' : tgt,  'fun' : fun,  'arg' : arg}
       else :
           params  =  { 'client' 'local' 'tgt' : tgt,  'fun' : fun,  'arg' : arg,  'expr_form' 'list' }
       obj  =  urllib.urlencode(params)
       content  =  self .postRequest(obj)
       result  =  content[ 'return' ][ 0 ]
       return  result
   def  allMinionKeys( self ):
     '''
      返回所有Minion keys;
      分别为 已接受、待接受、已拒绝;
      :return: [u'local', u'minions_rejected', u'minions_denied', u'minions_pre', u'minions']
      '''
       params  =  { 'client' 'wheel' 'fun' 'key.list_all' }
       obj  =  urllib.urlencode(params)
       content  =  self .postRequest(obj)
       minions  =  content[ 'return' ][ 0 ][ 'data' ][ 'return' ][ 'minions' ]
       minions_pre  =  content[ 'return' ][ 0 ][ 'data' ][ 'return' ][ 'minions_pre' ]
       minions_rej  =  content[ 'return' ][ 0 ][ 'data' ][ 'return' ][ 'minions_rejected' ]
      # return minions, minions_pre, minions_rej
       return  minions
   def  actionKyes( self , keystrings, action):
      '''
      对Minion keys 进行指定处理;
     :param keystrings: 将要处理的minion id字符串;
      :param action: 将要进行的处理,如接受、拒绝、删除;
      :return:
     {"return": [{"tag": "salt/wheel/20160322171740805129", "data": {"jid": "20160322171740805129", "return": {}, "success": true, "_stamp": "2016-03-22T09:17:40.899757", "tag": "salt/wheel/20160322171740805129", "user": "zhaogb", "fun": "wheel.key.delete"}}]}
      '''
       func  =  'key.'  +  action
        params  =  { 'client' 'wheel' 'fun' : func,  'match' : keystrings}
       obj  =  urllib.urlencode(params)
       content  =  self .postRequest(obj)
       ret  =  content[ 'return' ][ 0 ][ 'data' ][ 'success' ]
       return  ret
   def  acceptKeys( self , keystrings):
     '''
     接受Minion发过来的key;
     :return:
     '''
       params  =  { 'client' 'wheel' 'fun' 'key.accept' 'match' : keystrings}
       obj  =  urllib.urlencode(params)
       content  =  self .postRequest(obj)
       ret  =  content[ 'return' ][ 0 ][ 'data' ][ 'success' ]
       return  ret
   def  deleteKeys( self , keystrings):
     '''
     删除Minion keys;
     :param node_name:
     :return:
     '''
       params  =  { 'client' 'wheel' 'fun' 'key.delete' 'match' : keystrings}
       obj  =  urllib.urlencode(params)
       content  =  self .postRequest(obj)
       ret  =  content[ 'return' ][ 0 ][ 'data' ][ 'success' ]
       return  ret

     3)、views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# -*- coding: utf-8 -*-
from  __future__  import  unicode_literals
 
from  django.shortcuts  import  render
from  django.shortcuts  import  HttpResponse,HttpResponseRedirect,render_to_response
from  models  import  *
from  saltapi  import  salt_api
from  django.http  import  JsonResponse
import  json
 
def  index(request):
   accect  =  []
   context  =  accect_cmd.objects.values()
   for  in  context:
       accect.append(i[ "command" ])
   if  request.method  = =  "POST" :
       key  =  request.POST.get( 'key' )
       cmd  =  request.POST.get( 'cmd' )
       if  cmd.split( )[ 0 in  accect:
           spi  =  salt_api.SaltAPI( 'https://ip:8000' 'username' 'password' )
           result2  =  spi.masterToMinionContent(key,  'cmd.run' , cmd)
           return  JsonResponse(result2, safe = False )
       else :
           data  =  {key: "请检查命令是否正确或命令超权限,请联系管理员!" }
           return  JsonResponse(data, safe = False )
   else :
       return  render_to_response( 'index.html' )

     4)、models.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# -*- coding: utf-8 -*-
from  __future__  import  unicode_literals
from  django.db  import  models
 
# Create your models here.
 
class  accect_cmd(models.Model):
     command  =  models.CharField(max_length = 50 , unique = True , verbose_name = u '命令' )
     status  =  models.CharField(max_length = 20 , verbose_name = u '状态' )
     def  __unicode__( self ):
         return  u '{0} {1}' . format ( self .command,  self .status)
 
class  SaltReturns(models.Model):
     fun  =  models.CharField(max_length = 50 )
     jid  =  models.CharField(max_length = 255 )
     return_field  =  models.TextField(db_column = 'return' )
     success  =  models.CharField(max_length = 10 )
     full_ret  =  models.TextField()
     alter_time  =  models.DateTimeField()
     class  Meta:
         managed  =  False
         db_table  =  'salt_returns'
     def  __unicode__( self ):
         return  u '%s %s %s'  %  ( self .jid,  self . id self .return_field)
 
class  record(models.Model):
     time  =  models.DateTimeField(u '时间' , auto_now_add = True )
     comment  =  models.CharField(max_length = 128 , blank = True , default = '', null = True , verbose_name = u "记录" )
     def  __unicode__( self ):
         return  u '%s %s'  %  ( self .time,  self .comment)

      5)、index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
< html  lang = "en" >
< head >
   < meta  charset = "UTF-8" >
   < title >salt平台</ title >
   < script  src = "/static/jquery-2.1.1.min.js" ></ script >
</ head >
< body >
< form  action = "/salt/index/"  method = "POST"  id = "form" >
< div >主机:< input  type = "text"  name = "key"  value = ""  id = "a"  style = "width: 200px" ></ div >
< div >命令:< input  type = "text"  name = "cmd"  value = ""  id = "b"  style = "width: 200px" ></ div >
< div >< button  type = "button"  id = "fb" >执行</ button ></ div >
< div  style = "height: 300px;margin-top: 15px;" >
< textarea  type = "text"  style = "width: 60%;height: 300px"  disabled = "disabled"  class = "left"  name = "comment"  id = "c" ></ textarea >
</ div >
</ form >
</ body >
< script >
   $("#fb").click(function () {
       $.post("/salt/index/",{
         key:$("#a").val(),
         cmd: $("#b").val(),
       },
       function (response,status,xhr) {
         $("#c").html('')
         $.each(response,function (key,val) {
         var c = "\r\n"+key+ ":\r\n" + val;
         $("#c").append(c);
       })
      }
      )
     })
</ script >
</ html >

五、效果

   1)、单个key执行

     

b00370281eeb3e02f9dec5550f58ddfa.png

   2)、多个key执行

  

bfd4459cc59293d3241aca01ec7c23df.png

   3)、当命令不被许可时:

d0739d9709be059332ae66d14187ec98.png

六、总结

写的比较简陋,而且现在这个版本并不支持类似于192.168.1.1+,192.168.1.*这种正则匹配,后续会继续增加。



本文转自 sykmiao 51CTO博客,原文链接:http://blog.51cto.com/syklinux/1981943,如需转载请自行联系原作者

相关文章
|
6天前
|
监控 数据管理 测试技术
实现API接口的自动化
API接口自动化测试的最佳实践包括确定测试范围和目标、编写测试用例、选择合适的自动化测试工具、搭建测试环境、编写自动化测试脚本、执行自动化测试、分析测试结果和回归测试。通过这些步骤,可以提高测试效率和质量,确保API的稳定性和可靠性。此外,还介绍了如何利用API接口测试工具进行性能测试和压力测试,以及常见的挑战和解决方案。
|
3月前
|
JSON 数据挖掘 API
各大电商平台的商品详情数据接口(API接口系列)
各大电商平台的商品详情数据接口(API接口系列)是开发者在构建电商应用或进行数据分析时的重要工具。这些接口允许开发者通过编程方式获取商品的详细信息,如商品ID、标题、价格、库存、属性、描述、图片等。以下是对淘宝、京东、拼多多等电商平台商品详情数据接口的汇总,以及开发者在使用这些接口时需要注意的事项。
各大电商平台的商品详情数据接口(API接口系列)
|
3月前
|
编译器 API Android开发
Android经典实战之Kotlin Multiplatform 中,如何处理不同平台的 API 调用
本文介绍Kotlin Multiplatform (KMP) 中使用 `expect` 和 `actual` 关键字处理多平台API调用的方法。通过共通代码集定义预期API,各平台提供具体实现,编译器确保正确匹配,支持依赖注入、枚举类处理等,实现跨平台代码重用与原生性能。附带示例展示如何定义跨平台函数与类。
98 0
|
6天前
|
安全 测试技术 API
如何实现API接口的自动化测试?
实现API接口的自动化测试涉及多个关键步骤:确定测试范围和目标、编写测试用例、选择自动化测试工具、搭建测试环境、编写测试脚本、执行测试、分析结果和回归测试。选择合适的工具和考虑团队熟悉度是成功的关键。常用工具包括Postman、JMeter和SoapUI。通过这些步骤和工具,可以有效提高测试效率和质量,确保API的稳定性和可靠性。
|
1月前
|
API
阿里云短信平台API错误码提示错误天级流控显示小时级错误码
阿里云短信平台API错误码提示错误天级流控显示小时级错误码
|
2月前
|
缓存 测试技术 API
电商平台 API 接入技术要点深度剖析
本文介绍了高效使用电商平台API的关键步骤。首先,深入理解API文档,明确功能权限与参数格式要求;其次,选择合适的接入方式,如HTTP/HTTPS协议和RESTful API;接着,实施身份验证与授权机制,确保数据安全传输;此外,还需关注性能优化、安全防护、监控与日志记录,以提升系统稳定性和响应速度;最后,进行充分测试与调试,并关注API版本更新,确保长期兼容性。
|
2月前
|
JSON 供应链 数据挖掘
抖音商品sku数据接口(Dy.item_sku)丨抖音平台API数据接口指南
抖音商品详情SKU数据接口(Dy.item_sku)由抖音开放平台提供,用于获取商品详细信息,包括名称、价格、图片等。开发者需注册并获取权限,遵循API限制,通过商品ID调用接口,解析JSON格式返回数据。该接口广泛应用于商品展示、库存管理、订单处理及数据分析,助力提升工作效率和用户体验。使用时需遵守平台规则,确保数据安全。
|
3月前
|
监控 数据可视化 测试技术
Apifox 如何进行 API 自动化测试?经验之谈
选择 Apifox 来进行 API 自动化测试能够确保每次迭代的质量,避免引入新的 bug,还要实现自动化测试、定时测试、产品监控、可视化测试、持续集成等,帮助提高效率,通过设计和执行有针对性的测试用例,来全面验证产品功能,确保软件系统能够正常运行,减少上线后的问题。
Apifox 如何进行 API 自动化测试?经验之谈
|
3月前
|
测试技术 Android开发 iOS开发
Appium 是一个开源的自动化测试框架,它支持多种平台和多种编程语言
Appium是一款开源自动化测试框架,支持iOS和Android多平台及多种编程语言。通过WebDriver协议,开发者可编写自动化测试脚本。在iPhone上实现屏幕点击等操作需安装Appium及其依赖,启动服务器,并设置所需的测试环境参数。利用Python等语言编写测试脚本,模拟用户交互行为,最后运行测试脚本来验证应用功能。对于iPhone测试,需准备真实设备或Xcode模拟器。
111 1
|
3月前
|
Java API 数据中心
百炼平台Java 集成API上传文档到数据中心并添加索引
本文主要演示阿里云百炼产品,如何通过API实现数据中心文档的上传和索引的添加。

热门文章

最新文章