一、自定义创建模块

在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
 
#入库成功

saltstack(七)返回值的更多相关文章

  1. Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数

    Python第七天   函数  函数参数   函数里的变量   函数返回值  多类型传值     函数递归调用   匿名函数   内置函数 目录 Pycharm使用技巧(转载) Python第一天   ...

  2. (转)SpringMVC学习(七)——Controller类的方法返回值

    http://blog.csdn.net/yerenyuan_pku/article/details/72511844 本文所有案例代码的编写均建立在前文SpringMVC学习(六)——SpringM ...

  3. 无废话Android之activity的生命周期、activity的启动模式、activity横竖屏切换的生命周期、开启新的activity获取他的返回值、利用广播实现ip拨号、短信接收广播、短信监听器(6)

    1.activity的生命周期 这七个方法定义了Activity的完整生命周期.实现这些方法可以帮助我们监视其中的三个嵌套生命周期循环: (1)Activity的完整生命周期 自第一次调用onCrea ...

  4. Action的返回值类型总结

    Action的返回值 MVC 中的 ActionResult是其他所有Action返回类型的基类,下面是我总结的返回类型,以相应的帮助方法: 下面是这些方法使用的更详细的例子 一.返回View     ...

  5. c#中命令copy已退出,返回值为1

    c#中命令copy已退出,返回值为1 本正经的道:董姐刚才你说的修心养性其中的'修心'我 有孕在身刚好由戴梦瑶顶替了她的位置按照的指示 ╋旆呆 湎术葶页 邾箕砜笳 烦璜卿廑 奶奶个腿儿的等下次非让你 ...

  6. SSM-SpringMVC-21:SpringMVC中处理器方法之返回值Object篇

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 今天要记录的是处理方法,返回值为Object的那种,我给它分了一下类: 1.返回值为Object数值(例如1) ...

  7. springMVC对于Controller返回值的可选类型

    2018-01-11 对于springMVC处理方法支持支持一系列的返回方式:  (1)ModelAndView (2)Model (3)ModelMap (4)Map (5)View (6)Stri ...

  8. 总结day7 ---- 函数的内容 ,初识,返回值,进阶(一)

    内容大纲: 一: 函数识别 二: 函数的结构 三: 函数的返回值, 四: 函数的参数 五: 动态参数 六: 形参的顺序 七: 名称空间 八: 作用域 九: 加载顺序和取值顺序 十: 内置函数 十一: ...

  9. mybatis Mapper 中resultType使用方法及返回值为Map的写法

    mybatis学习(七)——resultType解析 resultType是sql映射文件中定义返回值类型,返回值有基本类型,对象类型,List类型,Map类型等.现总结一下再解释 总结: resul ...

随机推荐

  1. Same origin policy

    Chrome: Origin null is not allowed by Access-Control-Allow-Origin 的问题 发送 http request 时遇到 error: Ori ...

  2. 05_锅炉压力案例_java实现

    最开始是有机顶盒,后来电视里面都带着一个安卓的设备.现在空调.冰箱.洗衣机都跃跃欲试地想把这个东西加上.海尔出了一款智能冰箱,就是在冰箱门上嵌了一个12寸的屏幕.这个屏幕实际上就是一个安卓的平板似的. ...

  3. bzoj 1637: [Usaco2007 Mar]Balanced Lineup【瞎搞】

    我是怎么想出来的-- 把种族为0的都变成-1,按位置x排升序之后,s[i]表示种族前缀和,想要取(l,r)的话就要\( s[r]-s[l-1]==0 s[r]==s[l-1] \),用一个map存每个 ...

  4. Java实现短信中提取号码

    Description 提取一条短信里所有的电话号码,电话号码之间换行打印,短信的内容由用户输入. Input 第一行有个整数n(1≤n≤1000)表示测试用例的个数.其后的每一行中有一条短信,每一条 ...

  5. 微信小程序资源

    1.http://blog.csdn.net/wyx100/article/details/52667518 2.http://mp.weixin.qq.com/s?__biz=MzIyMDM2Mjg ...

  6. Http协议对格式、请求头、方法

    ######### #概览 ######### 超文本传输协议(Http: Hyper Text Transfer Protocol) :用于发送WWW方式的数据.采用TCP/IP协议,是一个无状态协 ...

  7. CircuitBreaker design pattern---reference

    It's common for software systems to make remote calls to software running in different processes, pr ...

  8. T-SQL编程以及常用函数

    1.索引添加索引,设计界面,在任何一列前右键--索引/键--点击进入添加某一列为索引 2.视图 视图就是我们查询出来的虚拟表创建视图:create view 视图名 as SQL查询语句,分组,排序, ...

  9. NHibernate3.2学习笔记

    一.开发环境 数据库:SQLServer2008 编译器:VS2010 .Net版本:.Net Framework 4.0 二.涉及第三方程序集 NHibernate.dll:版本3.2 Iesi.C ...

  10. c++利用jsoncpp libcurl 构造http 包(原)

    我们手游要接入uc九游进行测试,要用http向uc那边的sdk 服务器post  json数据. 虽然他们提供了php,java还有c#的服务端demo,但是我们服务器是C++写的,我实在不想中间再转 ...