使用salt-api來搭建salt自動(dòng)化平臺

一、介紹

創(chuàng)新互聯(lián)建站提供高防服務(wù)器、云服務(wù)器、香港服務(wù)器、服務(wù)器托管

    通常使用saltstack都是在master的服務(wù)器上直接命令操作,這個(gè)對于運(yùn)維人員來說不是什么大事,但是也會有出錯(cuò)的時(shí)候,而一旦出錯(cuò),就會有不可挽回的后果。

二、框架

    這里使用django框架,通過對salt-api的封裝,傳入命令,執(zhí)行api,將結(jié)果返回到頁面上顯示。注意:為了防止誤操作,我們對傳入的命令進(jìn)行了檢查,所有被定義的危險(xiǎn)命令將不會被執(zhí)行。(我這里為了簡單,所以定義了可以被執(zhí)行的命令。),前端使用了jquery+ajax的方式來不刷新頁面就將結(jié)果顯示在頁面上的方式。

三、salt-api的安裝

    網(wǎng)上教程很多,我這里就不再廢話了。

四、django代碼

   1)、整體結(jié)構(gòu)

        使用salt-api來搭建salt自動(dòng)化平臺

    2)、salt_api.py(這里參照了github上dzhops的代碼)

# -*- 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,返回的結(jié)果是內(nèi)容,不是jid;
        目標(biāo)參數(shù)tgt是一個(gè)如下格式的字符串:'*' 或 '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 進(jìn)行指定處理;
    :param keystrings: 將要處理的minion id字符串;
     :param action: 將要進(jìn)行的處理,如接受、拒絕、刪除;
     :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發(fā)過來的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

# -*- 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 i 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:"請檢查命令是否正確或命令超權(quán)限,請聯(lián)系管理員!"}
          return JsonResponse(data, safe=False)
  else:
      return render_to_response('index.html')

     4)、models.py

# -*- 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'狀態(tài)')
    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'時(shí)間', 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

<!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>主機(jī):<input type="text" name="key" value="" id="a" ></div>
<div>命令:<input type="text" name="cmd" value="" id="b" ></div>
<div><button type="button" id="fb">執(zhí)行</button></div>
<div >
<textarea type="text"  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)、單個(gè)key執(zhí)行

     

使用salt-api來搭建salt自動(dòng)化平臺

   2)、多個(gè)key執(zhí)行

  

使用salt-api來搭建salt自動(dòng)化平臺

   3)、當(dāng)命令不被許可時(shí):

使用salt-api來搭建salt自動(dòng)化平臺

六、總結(jié)

寫的比較簡陋,而且現(xiàn)在這個(gè)版本并不支持類似于192.168.1.1+,192.168.1.*這種正則匹配,后續(xù)會繼續(xù)增加。

當(dāng)前名稱:使用salt-api來搭建salt自動(dòng)化平臺
本文網(wǎng)址:http://bm7419.com/article38/igcgpp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、手機(jī)網(wǎng)站建設(shè)云服務(wù)器、網(wǎng)站制作移動(dòng)網(wǎng)站建設(shè)、建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作