终于来了个重量级的,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,函数名,函数参数,等等信息
[INFO ] 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' --return file 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' --return syslog 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,成功了