STATE MODULES
状态模块作为一个映射到salt states的实际执行和管理组件。
STATES ARE EASY TO WRITE!
在sls中定义的数据结构直接映射到salt modules,映射关系如下:
1 /etc/salt/master: # maps to "name" 2 file.managed: # maps to <filename>.<function> 3 - user: root # one of many options passed to the manage function 4 - group: root 5 - mode: 644 6 - source: salt://salt/master
详细的使用方法查看https://github.com/saltstack/salt/tree/develop/salt/states/file.py里面定义的用法
USING CUSTOM STATE MODULES
自定义的state modules被定义在file_roots的_states目录下,自定义模块在执行state.apply,saltutil.sync_states or saltutil.sync_all函数时触发
自定义的states将被分发到minion上,执行时的模块名需要去除后缀名,名称可以通过 __virtual__ function被修改。
CROSS CALLING EXECUTION MODULES FROM STATES
在states里面调用执行模块,执行模块和状态模块都可以使用__salt__和__grains__.
详细可以参看https://docs.saltstack.com/en/2016.11/ref/modules/index.html#cross-calling-execution-modules讲解
需要注意的是,除非需要,状态管理的实际工作不应在状态模块中进行。一个很好的例子是PKG状态模块,该模块不做任何计划的管理工作,它只是调用pkg执行模块。这使得PKG状态模块完全通用的,这就是为什么只有一个PKG状态模块和执行模块的后端PKG。
另一方面,一些模块要求将逻辑放在状态模块中,文件模块的一个很好的例子。但在绝大多数情况下,这不是最好的方法,编写特定的执行模块来完成后端工作将是最佳解决方案。
CROSS CALLING STATE MODULES
交叉调用state modules
所有的salt module函数可以相互调用,状态模块可以调用其他状态模块的功能,__states__变量包被装在到模块之后会被加载到minion端。
__states__是包含所有模块的一个字典,字典键是模块名,字典值是函数自身(有点像Python里面的反射功能),下面是调用示例:
ret = __states__['file.managed'](name='/tmp/myfile', source='salt://myfile')
示例:
1 def foo(bar): 2 return __salt __ ['cmd.run'](bar)
以上的代码会调用file状态模块,模块通过参数name和source传入
RETURN DATA
state module必须返回一个包含一下键值对的字典结构数据:
name: 值为state module名
changes:描述变化的字典,譬如下面这个描述执行安装软件包的字典内容
ret['changes'].update({'my_pkg_name': {'old': '', 'new': 'my_pkg_name-1.0'}})
result:是一个包含三种状态的值,True是执行成功,False是执行失败,None表示运行的是test模式之下,如test=True
live mode test mode
no changes True True
successful changes True None
failed changes False None
注意:在test模式下不能确认在运行之后是否会真正成功
comment:一个包含结果摘要的字符串
返回的数据也可以是包含pchanges键,代表预测性的变化。
注意:salt返回的数据必须是可序列化的。
TEST STATE
在实际运行之前需要先使用test测试运行一下,确保没有预测的错误出现。
示例:
1 # Return comment of changes if test. 2 if __opts__['test']: 3 ret['result'] = None 4 ret['comment'] = 'State Foo will execute with param {0}'.format(bar) 5 return ret
WATCHER FUNCTION
添加监视函数功能,编写状态检查模块
MOD_INIT INTERFACE
元数据刷新函数模块
示例:
1 def mod_init(low): 2 ''' 3 Refresh the package database here so that it only needs to happen once 4 ''' 5 if low['fun'] == 'installed' or low['fun'] == 'latest': 6 rtag = __gen_rtag() 7 if not os.path.exists(rtag): 8 open(rtag, 'w+').write('') 9 return True 10 else: 11 return False
LOG OUTPUT
模块的自定义日志输出
1 import logging 2 3 log = logging.getLogger(__name__) 4 5 log.info('Here is Some Information') 6 log.warning('You Should Not Do That') 7 log.error('It Is Busted')
STRINGS AND UNICODE
状态模块的字符类型问题,由于在python2里面使用的是unicode,在pyhton3使用的是str,编写人员可以通过__salt_system_encoding__得到系统的编码类型,譬如 'my_string'.encode(__salt_system_encoding__')
FULL STATE MODULE EXAMPLE
下面是一个比较完整的自定义的状态模块,它调用执行模块去执行去进行实际的执行操作。
1、确保自定义模块被放置在定义好的file_roots下的_states目录下
2、分发自动以state模块到minion端
salt '*' saltutil.sync_states
3、编写一个新的state文件(sls文件)使用自定义模块的功能
4、在新的state文件里面使用自定义功能的示例内容:
1 human_friendly_state_id: # An arbitrary state ID declaration. 2 my_custom_state: # The custom state module name. 3 - enforce_custom_thing # The function in the custom state module. 4 - name: a_value # Maps to the ``name`` parameter in the custom function. 5 - foo: Foo # Specify the required ``foo`` parameter. 6 - bar: False # Override the default value for the ``bar`` parameter.
一个完整的state modules示例:
1 import salt.exceptions 2 3 def enforce_custom_thing(name, foo, bar=True): #自定义state模块 4 ''' 5 Enforce the state of a custom thing 6 7 This state module does a custom thing. It calls out to the execution module 8 ``my_custom_module`` in order to check the current system and perform any 9 needed changes. 10 11 name 12 The thing to do something to 13 foo 14 A required argument 15 bar : True 16 An argument with a default value 17 ''' 18 ret = { #定义return数据字段信息 19 'name': name, 20 'changes': {}, 21 'result': False, 22 'comment': '', 23 'pchanges': {}, 24 } 25 26 # Start with basic error-checking. Do all the passed parameters make sense 27 # and agree with each-other? 28 if bar == True and foo.startswith('Foo'): #参数检查 29 raise salt.exceptions.SaltInvocationError( 30 'Argument "foo" cannot start with "Foo" if argument "bar" is True.') 31 32 # Check the current state of the system. Does anything need to change? 33 current_state = __salt__['my_custom_module.current_state'](name) 34 35 if current_state == foo: #检查自定义模块下的函数 36 ret['result'] = True 37 ret['comment'] = 'System already in the correct state' 38 return ret 39 40 # The state of the system does need to be changed. Check if we're running 41 # in ``test=true`` mode. 42 if __opts__['test'] == True: #设置test功能块 43 ret['comment'] = 'The state of "{0}" will be changed.'.format(name) 44 ret['pchanges'] = { 45 'old': current_state, 46 'new': 'Description, diff, whatever of the new state', 47 } 48 49 # Return ``None`` when running with ``test=true``. 50 ret['result'] = None 51 52 return ret 53 54 # Finally, make the actual change and return the result. 55 new_state = __salt__['my_custom_module.change_state'](name, foo) 56 57 ret['comment'] = 'The state of "{0}" was changed!'.format(name) 58 59 ret['changes'] = { 60 'old': current_state, 61 'new': new_state, 62 } 63 64 ret['result'] = True 65 66 return ret
参考链接:http://lixcto.blog.51cto.com/all/4834175/1