开发者社区> 技术小阿哥> 正文

使用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( )[0in 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.idself.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,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
「数据中心运维」集成和自动化的平台 StackStorm概述
「数据中心运维」集成和自动化的平台 StackStorm概述
8 0
【实测】django平台启动某脚本时的引入问题 (一期自动化平台的同学必看!)
【实测】django平台启动某脚本时的引入问题 (一期自动化平台的同学必看!)
8 0
【自动化测试】自动化平台的分层思想
【自动化测试】自动化平台的分层思想
12 0
龙蜥自动化平台 SysOM 2.1 热补丁中心介绍 | 第 74 期
了解热补丁中心相关功能使用,并通过案例展示学习使用热补丁中心的基本操作方法。
36 0
使用Docker部署自动化CI/CD平台Drone
[Drone](https://drone.io) 是一个现代化的持续集成平台,能够使用强大的云原生管道引擎自动化他们的构建、测试和发布工作流程,让我们不再关注程序如何发布而是如何去实现,去更好的实现。
585 0
windows下基于krpano的全自动化处理平台
本文介绍了一种基于krpano的全自动处理平台,可以自动发布全景实战案例。该平台完整构建了完整的生命周期,从图片上传,到后台图片切片等,基本具备服务能力。
275 0
「连接平台」钉钉与电商ERP系统打通,流程超自动化助力业务起飞
数环通基于连接平台iPass能力完成了与钉钉的深度融合,打通了电商平台与企业ERP系统之间的数据桥梁,应用通过连接平台的数据处理和字段匹配做串联,实现数据线上线下自动同步与集成,提高企业运营管理效率和准确性,为企业数字化赋能升级。
899 0
热饭的测开成果盘点第二十六期:IOS自动化平台
热饭的测开成果盘点第二十六期:IOS自动化平台
66 0
热饭的测开成果盘点第二十七期:安卓自动化平台
热饭的测开成果盘点第二十七期:安卓自动化平台
70 0
+关注
技术小阿哥
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
TcpRT:面向大规模海量云数据库的服务质量实时采集与诊断系
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载