基於salt自帶returners入庫功能的二次開發

    SaltStack自帶將執行的命令及返回結果入庫的功能,這裏我使用的是mysql庫。

    環境:

            RHEL AS5.8 64位

            Mysql 5.5

            Salt 2014.7.0

    首先介紹官方的標準實現方式,在mysql中建立salt所使用的用戶,然後建立salt庫、保存執行命令相關信息的jids表和保存命令執行結果的salt_returns表。創建庫及表的命令如下,這個salt官方給出的標準:


#########################################

本文出自Guibin的博客,http://guibin.blog.51cto.com/8909901/1606747

由Guibin原創,轉載請註明出處,我會不定期對本博文進行修正。

#########################################


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;

安裝數據庫驅動:

yum install -y python26-mysqldb

聲明數據庫類型、數據庫相關信息,在master配置中增加如下內容,然後重啓master使配置生效:

# vi /etc/salt/master
master_job_cache: mysql
#MySQL
mysql.host: '127.0.0.1'
mysql.user: 'micro'
mysql.pass: 'blog'
mysql.db: 'salt'
mysql.port: 3306

    這時執行個命令測試下:

# salt 'zhaogb-201' test.ping

    先查看庫中執行命令的相關信息(我的mysql用戶沒有設置密碼):

[root@localhost returners]# mysql salt -e 'select * from jids\G'
*************************** 1. row ***************************
  jid: 20150121174905627607
load: {"tgt_type": "glob", "jid": "20150121174905627607", "cmd": "publish", "tgt": "zhaogb-201", "kwargs": {"show_timeout": false, "show_jid": false}, "ret": "", "user": "root", "arg": [], "fun": "test.ping"}

    再查看命令返回的結果:

[root@localhost returners]# mysql salt -e 'select * from salt_returns\G'
*************************** 1. row ***************************
       fun: test.ping
       jid: 20150121174905627607
    return: true
        id: zhaogb-201
   success: 1
  full_ret: {"fun_args": [], "jid": "20150121174905627607", "return": true, "retcode": 0, "success": true, "cmd": "_return", "_stamp": "2015-01-21T17:49:09.942590", "fun": "test.ping", "id": "zhaogb-201"}
alter_time: 2015-01-21 17:49:09

    

    這是常規的使用,如果有些特殊需求,就需要進行二次開發,比如使用salt執行更新應用程序配置文件的時候,配置文件中有GB2312編碼的字符,夾雜在return的字典中,與utf-8編碼的字符混合,這時候入庫就會失敗,會報json.dumps遇到錯誤。

    我採用的解決方案是在salt源碼的基礎上進行修改,修改了入庫模塊mysql.py的returner、save_load方法。以下代碼解決兩個問題:
1. 命令執行結果入庫,若是執行的state.sls或state.highstate,則判斷return鍵的值是否是gb2312編碼,若是,則轉爲UTF8,然後再入庫;

2. 執行的命令入庫時,剔除超時的saltutil.find_job命令;

代碼如下:

def returner(ret):
    '''
    Return data to a mysql server
    '''
#################### 2015-01-26 #############################
    try:
        testJson = json.dumps(ret['return'])
    except:
        if ret['fun'] == 'state.sls' or ret['fun'] == 'state.highstate':
            for retK,retV in ret['return'].iteritems():
                if isinstance(ret['return'][retK], dict):
                    for retK2,retV2 in ret['return'][retK].iteritems():
                        if retK2 == 'changes':
                            if isinstance(ret['return'][retK][retK2], dict):
                                for retK3,retV3 in ret['return'][retK]['changes'].iteritems():
                                    if retK3 == 'diff':
                                        try:
                                            testJson22 = json.dumps(ret['return'][retK]['changes'][retK3])
                                        except:
                                            ret['return'][retK]['changes'][retK3] = retV3.decode('gb2312').encode('utf-8')
                                    else:
                                        continue
                        else:
                            continue
                else:
                    continue
#################### 2015-01-26 #############################

    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'],
                          json.dumps(ret['return']),
                          ret['id'],
                          ret['success'],
                          json.dumps(ret)))


def save_load(jid, load):
    '''
    Save the load to the specified jid id
    '''
####### editt 2015.01.21 ###########
    if load['fun'] == "saltutil.find_job":
        pass
    else:
        with _get_serv(commit=True) as cur:
    
            sql = '''INSERT INTO `jids`
                   (`jid`, `load`)
                    VALUES (%s, %s)'''

            cur.execute(sql, (jid, json.dumps(load)))


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章