saltstack(七)返回值

  一、自定义创建模块

在base目录下创建_modules目录,你自己编写的模块都可以存放在该目录下,当前目录结构下:

 

1
2
3
4
5
6
7
8
[root@localhost:] # tree -L 3 salt
salt
├── etc
├── _grains
│   ├── dmp_scribe.py
│   └── zabbix_conf.py
├── _modules
│   └── ip.py

通过上图可以看到已经创建了一个名为ip.py文件,看看相关内容:

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
 
import commands
 
def eth1():
     ip = {}
     cmd = "ifconfig eth1|grep inet|awk '{print $2}'|awk -F : '{print $2}'"
     ip2 = commands.getoutput(cmd).strip()
     ip[ 'ip' ] = ip2
     return ip

定义模块我们没有在/srv/salt/top.sls文件中新增模块名,现在把写好的模块同步到你需要执行的机器上,可以全部同步,也可以针对性的同步

这里只演示同步一台

1
2
3
salt '192.168.10.128' saltutil.sync_modules
192.168 . 10.128 :
     - modules.ip

在master执行编写的模块,由于不依赖state.sls文件,所以执行时命令也有变化,在主要命令后面跟模块名●函数名

1
2
3
4
5
[root@localhost _modules] # salt '192.168.10.128' ip.eth1
192.168 . 10.128 :
     - - - - - - - - - -
     ip:
         192.168 . 10.128

  二、屏幕返回值输出到指定的位置

saltstack执行命令时默认的返回值都是打印在当前屏幕上的,如果一次执行多台机器,怎么查看这些记录,为了更方便的查看这些返回结果的信息,这就用到了salt的returners功能了。关于详细介绍请参考官网地址:http://docs.saltstack.cn/ref/returners/index.html?highlight=returners

 

在/srv/salt目录下创建_returners目录,将自己编写的模块都可以存放在该目录下。

1
2
3
4
5
├── _returners
│   ├── local_return.py            #输出到文件
│   ├── mysql_log.py               #输出到数据库
│   ├── nohup.out
│   ├── salt_event_to_mysql.py

 在_returners目录下创建了两个文件,一个是local_return.py:表示把执行结果存在在本地

                                                                一个是mysql_log.py:表示把结果存放在mysql数据库中

    1、返回结果存放到本地
1
2
3
4
5
6
7
8
#coding:utf-8
def __virtual__():
    '''调用时的名字'''
    return "local_return"
def returner(ret):
     f = open ( '/var/log/salt/local_returner.log' , 'a+' )
     f.write( str (ret)[ 1 : - 1 ] + '\n' )
     f.close()

和自建模块一样,在编写完returners之后,也要同步到客户端的,同步的规则和自建模块一样。

 

1
salt '192.168.10.128'  saltutil.sync_returners

 在执行完上面的语句后,执行salt  ‘192.168.10.128’cmd.run 'uptime' --return local_return

 验证结果是否已经输出到文件中

   2、返回结果存放在mysql中

 官方默认returners中已经包含了mysql的returners,我们先直接利用官方原生的mysql returners,里面有创建相关表的语句。

 官方的mysql returners源码在https://github.com/saltstack/salt/blob/develop/salt/returners/mysql.py

 mysql服务器192.168.10.129:

 

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
#在mysql服务器上创建表
CREATE DATABASE  `salt`
       DEFAULT CHARACTER SET utf8
       DEFAULT COLLATE utf8_general_ci;
 
     USE `salt`;
 
     - -
     - - Table structure for table `jids`
     - -
 
     DROP TABLE IF EXISTS `jids`;
     CREATE TABLE `jids` (
       `jid` varchar( 255 ) NOT NULL,
       `load` mediumtext NOT NULL,
       UNIQUE KEY `jid` (`jid`)
     ) ENGINE = InnoDB DEFAULT CHARSET = utf8;
 
     - -
     - - Table structure for table `salt_returns`
     - -
 
     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;

给相关salt表赋予访问权限:

1
GRANT ALL PRIVILEGES ON salt. * TO 'salt' @localhost IDENTIFIED BY 'saltt' ;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql> show databases;
+ - - - - - - - - - - - - - - - - - - - - +
| Database           |
+ - - - - - - - - - - - - - - - - - - - - +
| information_schema |
| salt               |
+ - - - - - - - - - - - - - - - - - - - - +
2 rows in set ( 0.00 sec)
 
mysql> use salt
mysql> show tables;
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Tables_in_salt             |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| jids                       |
| salt_returners             |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - +

     因为要把客户端执行命令的结果直接返回给mysql服务器,所以客户端也要配置mysql信息的,我们以192.168.10.128为例,在salt的配置文件中加入如下信息,你也可以把它单独写在一个文件中。为了方便管理推荐写在单独文件中:

1
2
3
4
5
6
#/etc/salt/minion.d/mysql.conf
mysql.host: '192.168.1.204'
mysql.user: 'salt'
mysql. pass : 'salt'
mysql.db: 'salt'
mysql.port: 3306

然后在master上执行命令,如下:

1
2
salt   '192.168.10.128' cmd.run 'uptime' - - return local_return
salt   '192,168.10.128' cmd.run 'uptime' - - return mysql

注意这里用的是salt官网原生的mysql returners,并没有使用自己定义的mysql_log returners ,我们看看数据库中的记录:(图片是借鉴大神的图片)


 第一句是刚创建好表时的结果,可以看到数据库中已经有一条记录了,下面自己定义一个mysql_log returners来试试:

 

1
salt '192.168.10.128' cmd.run 'hostname' - - return mysql_log

我们来数据库中查看一下记录:


 下面附上定义的mysql_log.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
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
#/usr/bin/python
#coding:utf-8
from contextlib import contextmanager
import sys
import json
import logging
 
 
# Import third party libs
try :
     import MySQLdb
     HAS_MYSQL = True
except ImportError:
     HAS_MYSQL = False
 
log = logging.getLogger(__name__)
 
 
def __virtual__():
     if not HAS_MYSQL:
         return False
     return "mysql_log"
 
 
def _get_options():
     '''
     Returns options used for the MySQL connection.
     '''
     defaults = { 'host' : '192.168.1.204' ,
                 'user' : 'salt' ,
                 'pass' : 'salt' ,
                 'db' : 'salt' ,
                 'port' : 3306 }
     _options = {}
 
     # Ensure port is an int
     for attr in defaults:
         _attr = __salt__[ 'config.option' ]( 'mysql.{0}' . format (attr))
         if not _attr:
             log.debug( 'Using default for MySQL {0}' . format (attr))
             _options[attr] = defaults[attr]
             continue
         _options[attr] = _attr
     return _options
 
@contextmanager
def _get_serv(commit = False ):
     '''
     Return a mysql cursor
     '''
     _options = _get_options()
     conn = MySQLdb.connect(host = _options[ 'host' ], user = _options[ 'user' ], passwd = _options[ 'pass' ], db = _options[ 'db' ], port = _options[ 'port' ])
     cursor = conn.cursor()
     try :
         yield cursor
     except MySQLdb.DatabaseError as err:
         error, = err.args
         sys.stderr.write( str (error))
         cursor.execute( "ROLLBACK" )
         raise err
     else :
         if commit:
             cursor.execute( "COMMIT" )
         else :
             cursor.execute( "ROLLBACK" )
     finally :
         conn.close()
 
 
def returner(ret):
     '''
     Return data to a mysql server
     '''
     with _get_serv(commit = True ) as cur:
         sql = '''INSERT INTO `salt_returns`
                 (`fun`, `jid`, `return`, `id`, `success`, `full_ret` )
                 VALUES (%s, %s, %s, %s, %s, %s)'''
 
         cur.execute(sql, (ret[ 'fun' ], ret[ 'jid' ],
                             str (ret[ 'return' ]), ret[ 'id' ],
                             ret[ 'success' ], json.dumps(ret)))

    三、基于Salt Event系统构建Master端returner

上面我们介绍Saltstack的returner是由minion端主动连接returners完成执行结果的存储,在部分场景下并不能满足需求,由于salt底层已构建了一套Event系统,所有的操作均会产生event,因此基于Salt Event系统构建Master端returner成为一种可能。

SaltStack Event 系统 官网地址:http://docs.saltstack.com/en/latest/topics/event/index.html

SaltStack Event 系统监听events测试:http://pengyao.org/saltstack_event_system_listen_events.html

环境说明:

  • 测试结构:Master/Minions结构

  • Salt Version:2015.8.8.2

  • 本次测试结果将存放在mysql中

前置配置:

 安装Mysqldb依赖: yum -y install MySQL-Python

 配置本次测试需要使用的数据库及用户:

 

1
2
3
4
5
6
# 创建salt数据库
mysql - e 'create database salt'
# 创建用于连接salt数据库的用户
mysql - e '"grant all on salt.* to salt@localhost identified by "salt_pass' ;
# 将数据库配置添加至master配置文件中
echo - e "\n\n# MySQL\nmysql.host: 'localhost'\nmysql.user: 'salt'\nmysql.pass: 'salt_pass'\nmysql.db: 'salt'\nmysql.port: 3306" >> / etc / salt / master

为了与salt自带的mysql returners兼容,本次直接使用mysql returners对应的数据库表结构:

 

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
USE `salt`;
 
- -
- - Table structure for table `jids`
- -
 
DROP TABLE IF EXISTS `jids`;
CREATE TABLE `jids` (
   `jid` varchar( 255 ) NOT NULL,
   `load` mediumtext NOT NULL,
   UNIQUE KEY `jid` (`jid`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
 
- -
- - Table structure for table `salt_returns`
- -
 
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;

编写returners:salt_event_to_mysql.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
31
32
33
34
35
36
37
38
39
40
#!/bin/env python
#coding=utf8
 
# Import python libs
import json
 
# Import salt modules
import salt.config
import salt.utils.event
 
# Import third party libs
import MySQLdb
 
__opts__ = salt.config.client_config( '/etc/salt/master' )
 
# Create MySQL connect
conn = MySQLdb.connect(host = __opts__[ 'mysql.host' ], user = __opts__[ 'mysql.user' ], passwd = __opts__[ 'mysql.pass' ], db = __opts__[ 'mysql.db' ], port = __opts__[ 'mysql.port' ])
cursor = conn.cursor()
 
# Listen Salt Master Event System
event = salt.utils.event.MasterEvent(__opts__[ 'sock_dir' ])
for eachevent in event.iter_events(full = True ):
     ret = eachevent[ 'data' ]
     if "salt/job/" in eachevent[ 'tag' ]:
         # Return Event
         if ret.has_key( 'id' ) and ret.has_key( 'return' ):
             # Igonre saltutil.find_job event
             if ret[ 'fun' ] = = "saltutil.find_job" :
                 continue
 
             sql = '''INSERT INTO `salt_returns`
                 (`fun`, `jid`, `return`, `id`, `success`, `full_ret` )
                 VALUES (%s, %s, %s, %s, %s, %s)'''
             cursor.execute(sql, (ret[ 'fun' ], ret[ 'jid' ],
                                  json.dumps(ret[ 'return' ]), ret[ 'id' ],
                                  ret[ 'success' ], json.dumps(ret)))
             cursor.execute( "COMMIT" )
     # Other Event
     else :
         pass

运行编写的returner:   Python salt_event_to_mysql.py

 

​测试:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
salt '*' test.ping     #开启一个终端,运行salt指令
 
#输出为:
salt - minion - 01.example .com:
     True
 
#检查mysql数据库,查询salt_returns表数据:
mysql salt - e "select * from salt_returns\G"
 
#输出为:
* * * * * * * * * * * * * * * * * * * * * * * * * * * 1. row * * * * * * * * * * * * * * * * * * * * * * * * * * *
     fun: test.ping
     jid: 20140417161103569310
     return : true
     id : salt - minion - 01.example .com
     success: 1
     full_ret: { "fun_args" : [], "jid" : "20140417161103569310" , "return" : true, "retcode" : 0 , "success" : true, "cmd" : "_return" , "_stamp" : "2014-04-17T16:11:03.584859" , "fun" : "test.ping" , "id" : "salt-minion-01.example.com" }
     alter_time: 2014 - 04 - 17 16 : 11 : 03
 
#入库成功

 

转载于:https://www.cnblogs.com/phennry/p/5572969.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值