昊漫玉 发表于 2018-8-1 10:33:42

saltstack(九)returner

  终于来了个重量级的,returner这东西简直是个神器啊。再也不用盯着管理端的屏幕看了,直接用returner这东西,把返回的结果同时保存在文件或者数据库里面一份。
  returner支持很多输出,比如各种各样的数据库,mysql,redis,monggodb。也支持输入到文件,或者/var/local/syslog里面。
  returner的工作过程是咋样的呢?楼主根据自己的实践总结了一下
  1。其实,也就是当我们把自定义的returner同步到minion上面去后,
  2.然后我们在master上执行一些操作,并指定return的对象,比如salt '*' cmd.run 'ls' --return mysql
  3.这个时候,master上面发送过来的命令会在,mininon上面执行。minion上执行完命令后,产生一个结果,在salt里面这个结果用ret表示,
  4.这个结果一方面会按照通常的方式返回给master并在master的屏幕上面输出打印。
  5.另一方面,ret这个结果会传给我们自定义的returner,然后在minion端执行returner,
  6.执行returner产生的结果就是把最终的结果导入文件或者数据库,这个和returner里面怎么写有关了。
  7.第二方面怎么玩,和master就不搭嘎了。
  8.注意:咱们returner里面咱们定义的文件或者数据库都是相对于minion来说,比如说我们把结果写入文件/tmp/returner里面,这个/tmp/returner是minion上面的,而不是在master上面的。楼主调试这个功能的时候,开始没搞清这层关系,吃了不小哦亏。
  9.其实,returner可以任意的定义,我们在里面定义了啥,它就可以干什么活,比如我们可以定义
  邮件,短信报警模块等等
  官方地址:
  https://github.com/saltstack/salt/blob/develop/salt/returners/mysql.py
  我们先测试一下return接口是否能够正常使用。同时看一下,我们自定义的returner究竟接受到什么样的数据?
  自定义returner默认路径是/srv/salt/_returners
mkdir /srv/salt/_returners  看一下测试returner
root@salt-master:~# cat /srv/salt/_returners/local.py  
from __future__ import print_function
  
def returner(ret):
  
    print(ret)
  
root@salt-master:~#
  好了,这个时候,咱们为了看得清楚点。到minion上面,以debug的模块启动minion
root@salt-client:~# /etc/init.d/salt-minion  
Usage: /etc/init.d/salt-minion {start|stop|status|restart|force-reload}
  
root@salt-client:~# /etc/init.d/salt-minion stop
  
[ ok ] Stopping salt minion control daemon: salt-minion.
  
root@ansible:~# salt-minion-l debug
  OK,master端同步一下returners
root@salt-master:~# salt '*' saltutil.sync_returners  
salt-client:
  
root@salt-master:~# salt '*'cmd.run   'hostname'--return    local
  
salt-client:
  
    salt-client
  
root@salt-master:~#
  到minion端看一下debug的信息。看到了没,大括号里面的东西,就是minion执行完毕后,返回给master
  或者返回给returner的东西。结构都是这个样子的
  大伙应该都看得懂,jid,函数名,函数参数,等等信息
Returning information for job: 20140624162233869962  
{'fun_args': ['hostname'], 'jid': '20140624162233869962', 'return': 'ansible',
  
'retcode': 0, 'success': True, 'fun': 'cmd.run', 'id': 'ansible'}
  好了,这个东西出来了说明咱们的returner是木有问题的。
  下面看一下,怎么把结果return到文件或者日志里面吧
  先看看文件吧
楼主的returner代码  
root@salt-master:~# cat /srv/salt/_returners/file.py
  
import json
  
import time
  

  
def returner(ret):
  
    now = time.localtime()
  
    now = time.strftime("%Y-%m-%d %H:%M:%S",now)
  
    result_file = '/tmp/returner'
  
    result = file(result_file,'a+')
  
    result.write('At'+str(json.dumps(now))+'\n')
  
    result.write(str(json.dumps(ret))+'\n')
  
    result.close()
  

  
同步一下returner
  
root@salt-master:~# salt '*' saltutil.sync_returners
  
ansible:
  
    - returners.file
  

  
执行个命令并return到file
  
root@salt-master:~# salt '*'cmd.run   'hostname'--returnfile
  
ansible:
  
    ansible
  

  
好查看一下minion上面的结果
  
root@salt-master:~# salt '*'cmd.run   'cat /tmp/returner'
  
ansible:
  
    At"2014-06-24 04:09:23"
  
    {"fun_args": ["hostname"], "jid": "20140624164743457542", "return": "ansible", "retcode": 0, "success": true, "fun": "cmd.run", "id": "ansible"}
  
    At"2014-06-24 04:09:47"
  
    {"fun_args": ["hostname"], "jid": "20140624164807042671", "return": "ansible", "retcode": 0, "success": true, "fun": "cmd.run", "id": "ansible"}
  
    At"2014-06-24 04:10:59"
  
    {"fun_args": ["hostname"], "jid": "20140624164918774162", "return": "ansible", "retcode": 0, "success": true, "fun": "cmd.run", "id": "ansible"}
  
root@salt-master:~#
  OK,搞定,再看看return到syslog
看一下代码,这里用到里前几篇说过的虚拟模块  
root@salt-master:~# cat /srv/salt/_returners/syslog.py
  
import json
  
try:
  
    import syslog
  
    HAS_SYSLOG = True
  
except ImportError:
  
    HAS_SYSLOG = False
  

  
__virtualname__ = 'syslog'
  

  
def __virtual__():
  
    if not HAS_SYSLOG:
  
      return False
  
    return __virtualname__
  
def returner(ret):
  
    syslog.syslog(syslog.LOG_INFO, 'salt-minion: {0}'.format(json.dumps(ret)))
  

  
同步一下returner
  
root@salt-master:~# salt '*' saltutil.sync_returners
  
ansible:
  
    - returners.syslog
  

  
执行个命令玩玩
  
root@salt-master:~# salt '*'cmd.run   'hostname'--returnsyslog
  
ansible:
  
    ansible
  
看一下minion上的syslog日志。
  
root@salt-master:~# salt '*'cmd.run   'grep 'jid' /var/log/syslog'
  
ansible:
  

  
Jun 24 04:15:19 ansible salt-minion: salt-minion: {"fun_args":
  
["hostname"], "jid": "20140624165338927188", "return": "ansible",
  
"retcode": 0, "success": true, "fun": "cmd.run", "id": "ansible"}
  
root@salt-master:~#
  OK,搞定,不过感觉放在syslog不太好吧,syslog还有别的很多其他的日志消息。觉得,放文件的话,最后弄个空文件放。
  OK,下面该搞搞数据库,楼主只玩过mysql数据库,所以没得选择了。
  这个例子基本上算是,按照官网上来的,楼主在本地跑通就这个样子。
  注意:楼主的数据库是建立在master上面的,所以待会要需要远程连接
  先看一下建表语句:
    CREATE DATABASE`salt`  
      DEFAULT CHARACTER SET utf8
  
      DEFAULT COLLATE utf8_general_ci;
  

  
    USE `salt`;
  

  
    DROP TABLE IF EXISTS `salt_returns`;
  
    CREATE TABLE `salt_returns` (
  
      `fun` varchar(50) NOT NULL,
  
      `jid` varchar(255) NOT NULL,
  
      `return` mediumtext NOT NULL,
  
      `id` varchar(255) NOT NULL,
  
      `success` varchar(10) NOT NULL,
  
      `full_ret` mediumtext NOT NULL,
  
      `alter_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  
      KEY `id` (`id`),
  
      KEY `jid` (`jid`),
  
      KEY `fun` (`fun`)
  
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  看一下,returner吧
root@salt-master:~# cat /srv/salt/_returners/mysql_return.py  
import json
  
import time
  
try:
  
    import MySQLdb
  
    HAS_MYSQL = True
  
except ImportError:
  
    HAS_MYSQL = False
  

  
__virtualname__ = 'mysql'
  

  
def __virtual__():
  
   if not HAS_MYSQL:
  
       return False
  
   else:
  
       return__virtualname__
  
def returner(ret):
  
       conn=MySQLdb.connect(host='10.240.161.98',user='root',passwd='123456',db='salt',
  
                            port=3306)
  
       cursor=conn.cursor()
  
       sql = 'INSERT INTO salt_returns(`fun`,`jid`,`return`,`id`,`success`,`full_ret`)
  
             VALUES (%s,%s,%s,%s,%s,%s)'
  
       cursor.execute(sql % (str(json.dumps(ret['fun'])),str(json.dumps(ret['jid'])),
  
                      str(json.dumps(ret['return'])),str(json.dumps(ret['id'])),
  
                      '"'+str(ret['success'])+'"',"'"+json.dumps(ret)+"'"))
  
       conn.commit()
  
       cursor.close()
  
       conn.close()
  
root@salt-master:~#
  同步并执行一下
root@salt-master:~# salt '*' saltutil.sync_returners  
salt-minion:
  
    - returners.mysql_return
  
root@salt-master:~# salt '*'    cmd.run 'ls'   --return=mysql
  
salt-minion:
  
    1
  
    123
  
    dec1.py
  
root@salt-master:~#
  看一下数据库。
root@salt-master:~# mysql -uroot -p"123456" -e "select * from salt.salt_returns\G"  
*************************** 1. row ***************************
  
       fun: cmd.run
  
       jid: 20140625105655939721
  
    return: 1
  
123
  
dec1.py
  
      id: salt-minion
  
   success: True
  
full_ret: {"fun_args": ["ls"], "jid": "20140625105655939721", "return": "1
  
123
  
dec1.py", "retcode": 0, "success": true, "fun": "cmd.run", "id": "salt-minion"}
  
alter_time: 2014-06-25 10:56:55
  
root@salt-master:~#
  ok,成功了
页: [1]
查看完整版本: saltstack(九)returner