saltstack-模块的编写(三)saltstack的插件(四)log

虽然saltstack为我们提供很多模块,但是有时候还想自定义一些模块,那就涉及到模块的编写,在编写模块之前我们先了解一些内容。

一:__salt__变量的理解:如下是官网的解释

1 the variable __salt__ is packed into the modules after they are loaded into the Salt minion.
2 the __salt__ variable is a Python dictionary containing all of the Salt functions. Dictionary keys are strings
3 representing the names of the modules and the values are the functions themselves.

解释:变量__salt__ 当minion端的都加载完modules的时候,会创建(这里的创建可以理解是:所有的模块的名和对应的方法都加入到__salt__变量里。)一个变量__salt__。

__salt__变量是一个python字典,字典的内容包含了所有salt的函数方法。字典的key值是字符串,key值代表了salt的模块和方法的名字,value就是对应的模块的对应函数方法。

为什么要介绍__salt__变量,因为我们自定义的模块有可能使用到salt自身的模块的,通过__salt__字典,我们可以快速进行相关的设置。

二:__virtual__ Function:介绍

官方的介绍:

the __virtual__ function returns either a string, True, False, or False with an error string. If a string is
returned then the module is loaded using the name of the string as the virtual name. If True is returned the module
is loaded using the current module name. If False is returned the module is not loaded. False lets the module
perform system checks and prevent loading if dependencies are not met.

解释:函数__virtual__ 内置函数返回的是:一个字符串、布尔值:True、False或者False和一个错误的字符串值。当返回一个字符串的时候,一个名字为该字符串的模块被加载,如果返回的是True的时候,表示当前使用的模块的名字被加载,如果

返回的是False的时候,表示当前的模块没有被加载,当返回False的时候,会强制让模块系统检查和阻止加载该模块,如果依赖不匹配的。

言外之意:该函数的作用是检测当前加载的模块的是否合法。

三:编写模块,需要知道调用的在命令行传入参数的形式,避免不知道传参的类型,导致问题的发生。

在命令行:

1 salt '*'  op_red.con_re 127.0.0.1 6379  dd  ok 22

 

后台解析的命令行:

1 Command details {'tgt_type': 'glob', 'jid': '20161216003357190093', 'tgt': '*', 'ret': '', 'user': 'root', 'arg': ['127.0.0.1', 6379, 'dd', 'ok'], 'fun': 'op_red.con_re'}

 

换一个字典传入:

1 salt '*'  op_red.con_re 127.0.0.1 6379  set   {'tom':'cc'}

 

后台处理的参数详情:注意!!!!!如下标红的不是json串 只是个字符串~~~!!!             '{tom:cc}'

1  Command details {'tgt_type': 'glob', 'jid': '20161216004726926447', 'tgt': '*', 'ret': '', 'user': 'root', 'arg': ['127.0.0.1', 6379, 'set', '{tom:cc}'], 'fun': 'op_red.con_re'}

 

如下例子:

例子1:

'''
Cheese execution (or returner/beacon/etc.) module
'''
try:
    import enzymes
HAS_ENZYMES = True
except ImportError:
    HAS_ENZYMES = False
def __virtual__():
'''
only load cheese if enzymes are available
'''
if HAS_ENZYMES:
    return 'cheese'
else:
    return False, 'The cheese execution module cannot be loaded: enzymes..
,!unavailable.'

例子2:

'''
Cheese state module
'''
def __virtual__():
'''
only load cheese if enzymes are available
'''
# predicate loading of the cheese state on the corresponding execution module
if 'cheese.slice' in __salt__:
    return 'cheese'
else:
    return False, 'The cheese state module cannot be loaded: enzymes unavailable.'

salt还为我们提供了其他的字典__GRAINS__、__PILLAR__、__CONTEXT__  详细请看官网:https://docs.saltstack.com/en/latest/topics/development/dunder_dictionaries.html。

有了如上的介绍,我们可以进行自定义的模块的编写:

默认自定义模块文件目录:/srv/salt/_modules

创建该目录:mkdir -pv /srv/salt/_modules

创建自定义模块:

1 [root@localhost _modules]# cat test.py 
2 
3 def cmd(arg):
4   return __salt__['cmd.run'](arg)

minion端同步自定义模块:

1 [root@localhost _modules]# salt  '*'    saltutil.sync_modules 
2 salt_minion:
3     - modules.test
4 [root@localhost _modules]# 

执行自定义模块:

1 [root@localhost _modules]# salt '*' test.cmd w
2 salt_minion:
3      03:55:26 up 1 day, 23 min,  2 users,  load average: 0.18, 0.12, 0.14
4     USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
5     root     tty1     -                Thu01   12:05m  0.03s  0.03s -bash
6     root     pts/0    192.168.217.1    Sun15    6:45   0.05s  0.05s -bash 

需要注意的是:交叉调用salt模块的模式:__salt__['模块名字.函数名字'](参数)

__salt__['cmd.run'](arg)

如上是我们定义的参数不为空,当参数为空的时候,不能将()去掉。

[root@localhost _modules]# cat test1.py 
def cmd():
  return __salt__['network.ip_addrs']() 
[root@localhost _modules]# salt '*'  test1.cmd 
salt_minion:
    - 192.168.147.129
    - 192.168.217.143
[root@localhost _modules]# salt '*' test1.cmd 
salt_minion:
    - 192.168.147.129
    - 192.168.217.143
[root@localhost _modules]# cat test1.py 
def __virtual__():
  if __grains__.get('os_family','unkown')=='RedHat':
    return True 
  else:
    return False

def cmd():
  return __salt__['network.ip_addrs']()

对于函数有多个参数的时候,可以使用字符串的初始化。来拼凑出__salt__中的需要的参数如下:多个参数在调用模块的时候进行传入 如下例子:

[root@localhost _modules]# cat test1.py 
def __virtual__():
  if __grains__.get('os_family','unkown')=='RedHat':
    return True 
  else:
    return False

def cmd(x,y):
  arg='%s %s'%(x,y)
  return __salt__['cmd.run'](arg) 

[root@localhost _modules]# salt '*' test1.cmd id root
salt_minion:
    uid=0(root) gid=0(root) groups=0(root)

案例:

因为minon端。环境的不一样,或者一些网络限制。导致一些python安装包无法安装,这时候,minion端想练redis或者zk的情况下,我该如何写模块呢?

需求分析:

1、pip安装不了第三方模块。

2、只能使用python内置模块。

解决方案:

1、用socket 写客户端和服务器端进行连接。

弊端:性能无法保证。

2、既然saltstackmaster和 minion可以进行通信。而本身redis模块或者zk模块内的依赖较少,我们可以打一个python包,在当前master端的默认model路径进行导入,这样既保证性能也能保证需求。

[root@localhost _modules]# tree redis/
redis/
├── cheng.py
├── client.py
├── client.pyc
├── _compat.py
├── _compat.pyc
├── connection.py
├── connection.pyc
├── evil.py
├── exceptions.py
├── exceptions.pyc
├── foo.py
├── __init__.py
├── __init__.pyc
├── lock.py
├── lock.pyc
├── sentinel.py
├── sentinel.pyc
├── test1.py
├── utils.py
└── utils.pyc

0 directories, 20 files
1 [root@localhost _modules]# pwd
2 /srv/salt/_modules

 

外部调用的模块脚本:

[root@localhost _modules]# cat Operation_redis.py 
#!/usr/bin/env python
#-*-coding:utf-8-*-
# author:evil_liu
import redis

return_msg={'success':None,'fail':None}

def con_re(host,port,command,key=None):
    #check_arg(args)
    r=redis.Redis(host=host,port=port)
    if hasattr(r,command):
        func=getattr(r,command)
        ret=func(key)
        return_msg['success']=ret
        return return_msg
    else:
        help_msg_info='''
        use module example:
        salt '*' modulename.func  host port command arg
        '''
        return_msg['fail']='your command error!'
        return_msg.setdefault('help_msg',help_msg_info)
        return return_msg

使用方法:

 1 [root@localhost _modules]# salt '*' Operation_redis.con_re   127.0.0.1  6379 ddd
 2 salt_minion:
 3     ----------
 4     fail:
 5         your command error!
 6     help_msg:
 7         
 8                 use module example:
 9                 salt '*' modulename.func  host port command arg
10                 
11     success:
12         None

自定义redis模块支持 hash操作、普通操作:

  1 #!/usr/bin/env python
  2 #-*-coding:utf-8-*-
  3 # author:liumeide
  4 import redis
  5 import  sys
  6 
  7 return_msg={'success':True,'message':None}
  8 
  9 def __virual__():
 10     return  'jd_op_redis'
 11 
 12 
 13 def chec_env():
 14     '''
 15     检测当前目录是否在sys.path
 16     :return:无。
 17     '''
 18     if '' in sys.path:
 19         pass
 20     else:
 21         py_pa=sys.path.reverse()
 22         py_pa.append('')
 23         sys.path=py_pa.reverse()
 24 
 25 def con_re(host,port,command_set):
 26     r = redis.Redis(host=host, port=port)
 27     if isinstance(command_set,str):
 28         command_set=command_set.strip().split()
 29         if command_set[-1]=='True':#是hash查询。
 30             ret=chec_excu_moth(command_set,r)
 31             return ret
 32         elif command_set[-1]=='False':#是正常查询
 33             ret = command_excu(command_set,r)
 34             return ret
 35         else:
 36             return error_info()
 37     else:
 38         com_res=command_excu(r,command_set)
 39         return com_res
 40 
 41 
 42 def chec_excu_moth(x,r):
 43     '''
 44     功能:该函数主要是hash功能函数,查询用户传入的方法是否有效,如果有效执行,否则返回错误信息。
 45     :param x: 传入命令集合
 46     :param r: 当前redis连接
 47     :return: 返回错误结果或者执行结果。
 48     '''
 49     if len(x)==5:
 50         if hasattr(r,x[0]):
 51             func=getattr(r,x[0])
 52             ret=func(x[1],x[2],x[3])
 53             return_msg['success'] = True
 54             return_msg['message'] = ret
 55             return  return_msg
 56     if len(x)==4:
 57         if hasattr(r,x[0]):
 58             func=getattr(r,x[0])
 59             ret=func(x[1],x[2])
 60             return_msg['success'] = True
 61             return_msg['message'] = ret
 62             return return_msg
 63         else:
 64             return error_info()
 65 
 66 
 67 def  command_excu(command_set,r):
 68     '''
 69     功能:该函数主要是执行非hash操作。
 70     :param command_set: 传入的命令集合。
 71     :param r: redis连接。
 72     :return: 执行结果。
 73     '''
 74     if len(command_set)==4:
 75         if hasattr(r, command_set[0]):
 76             func = getattr(r, command_set[0])
 77             ret=func(command_set[1],command_set[2])
 78             return_msg['success'] = True
 79             return_msg['message'] = ret
 80             return return_msg
 81         else:
 82             return return_msg
 83     elif len(command_set)==3:
 84         if hasattr(r, command_set[0]):
 85             func = getattr(r, command_set[0])
 86             ret = func(command_set[1])
 87             return_msg['success'] = True
 88             return_msg['message'] = ret
 89             return return_msg
 90         else:
 91             return return_msg
 92     else:
 93         return_msg['message'] = 'your command error!'
 94         return_msg['success'] = False
 95         return return_msg
 96 def error_info():
 97     '''
 98     功能:该函数主要是错误信息返回。
 99     :return: 返回错误信息。
100     '''
101     return_msg['message'] = 'your command error!'
102     return_msg['success'] = False
103     return return_msg

saltstack的插件(四)log

一:日志输出:

可以通过loging模块来输出saltstack的日志输出。该日志是写在minion端的日志中。如下是简单的例子:

1 import logging
2 log = logging.getLogger(__name__)
3 log.info('Here is Some Information')
4 log.warning('You Should Not Do That')
5 log.error('It Is Busted')

 

学习是一种态度,坚持是质变的利器!
 
http://www.cnblogs.com/evilliu/articles/6170561.html
posted @ 2018-03-11 22:58  dion至君  阅读(371)  评论(0)    收藏  举报