官术网_书友最值得收藏!

Setting grains dynamically

As you already know, grains hold variables that describe certain aspects of a Minion. This could be information about the operating system, the hardware, the network, and so on. It can also contain statically defined user data, which is configured either in /etc/salt/minion or /etc/salt/grains. It is also possible to define grains dynamically using grains modules.

Setting some basic grains

Grains modules are interesting in that so long as the module is loaded, all public functions will be executed. As each function is executed, it will return a dictionary, which contains items to be merged into the Minion's grains.

Let's go ahead and set up a new grains module to demonstrate. We'll prepend the names of the return data with a z so that it is easy to find.

'''
Test module for Extending SaltStack

This module should be saved as salt/grains/testdata.py
'''


def testdata():
    '''
    Return some test data
    '''
    return {'ztest1': True}

Go ahead and save this file as salt/grains/testdata.py, and then use salt-call to display all of the grains, including this one:

# salt-call --local grains.items
local:
 ----------
...
 virtual:
 physical
 zmqversion:
 4.1.3
 ztest1:
 True

Keep in mind that you can also use grains.item to display only a single grain:

# salt-call --local grains.item ztest
local:
 ----------
 ztest1:
 True

It may not look like this module is much good, since this is still just static data that could be defined in the minion or grains files. But keep in mind that, as with other modules, grains modules can be gated using a __virtual__() function. Let's go ahead and set that up, along with a flag of sorts that will determine whether or not this module will load in the first place:

import os.path


def __virtual__():
    '''
    Only load these grains if /tmp/ztest exists
    '''
    if os.path.exists('/tmp/ztest'):
        return True
    return False

Go ahead and run the following commands to see this in action:

# salt-call --local grains.item ztest
local:
 ----------
 ztest:
# touch /tmp/ztest
# salt-call --local grains.item ztest
local:
 ----------
 ztest:
 True

This is very useful for gating the return data from an entire module, whether dynamic or, as this module currently is, static.

You may be wondering why that example checked for the existence of a file, rather than checking the existing Minion configuration. This is to illustrate that the detection of certain system properties is likely to dictate how grains are set. If you want to just set a flag inside the minion file, you can pull it out of __opts__. Let's go ahead and add that to the __virtual__() function:

def __virtual__():
    '''
    Only load these grains if /tmp/ztest exists
    '''
    if os.path.exists('/tmp/ztest'):
        return True
    if __opts__.get('ztest', False):
        return True
    return False

Go ahead and remove the old flag, and set the new one:

# rm /tmp/ztest
# echo 'ztest: True' >> /etc/salt/minion
# salt-call --local grains.item ztest
local:
 ----------
 ztest:
 True

Let's go ahead and set up this module to return dynamic data as well. Because YAML is so prevalent in Salt, let's go ahead and set up a function that returns the contents of a YAML file:

import yaml
import salt.utils


def yaml_test():
    '''
    Return sample data from /etc/salt/test.yaml
    '''
    with salt.utils.fopen('/etc/salt/yamltest.yaml', 'r') as fh_:
        return yaml.safe_load(fh_)

You may notice that we've used salt.utils.fopen() instead of a standard Python open(). Salt's fopen() function wraps Python's open() with some extra handling, so that files are closed properly on Minions.

Save your module, and then issue the following commands to see the result:

# echo 'yamltest: True' > /etc/salt/yamltest.yaml
# salt-call --local grains.item yamltest
local:
 ----------
 yamltest:
 True

(Not) cross-calling execution modules

You may be tempted to try to cross-call an execution module from inside a grains module. Unfortunately, that won't work. The __virtual__() function in many execution modules relies heavily on grains. Allowing grains to cross-call to execution modules, before Salt has decided whether or not to even the execution module in the first place, would cause circular dependencies.

Just remember, grains are loaded first, then pillars, then execution modules. If you have code that you plan to use two or more of these types of modules, consider setting up a library for it in the salt/utils/ directory.

The final grains module

With all of the code we've put together, the resulting module should look like the following:

'''
Test module for Extending SaltStack.

This module should be saved as salt/grains/testdata.py
'''
import os.path
import yaml
import salt.utils


def __virtual__():
    '''
    Only load these grains if /tmp/ztest exists
    '''
    if os.path.exists('/tmp/ztest'):
        return True
    if __opts__.get('ztest', False):
        return True
    return False


def testdata():
    '''
    Return some test data
    '''
    return {'ztest1': True}


def yaml_test():
    '''
    Return sample data from /etc/salt/test.yaml
    '''
    with salt.utils.fopen('/etc/salt/yamltest.yaml', 'r') as fh_:
        return yaml.safe_load(fh_)
主站蜘蛛池模板: 广宁县| 昆山市| 贵阳市| 龙川县| 钟祥市| 朝阳县| 芦溪县| 百色市| 丹阳市| 射阳县| 定边县| 来凤县| 广平县| 大名县| 广德县| 诸城市| 松潘县| 仁布县| 临澧县| 宣恩县| 郎溪县| 沅江市| 汉沽区| 丹棱县| 德令哈市| 浑源县| 东兴市| 延长县| 神木县| 边坝县| 缙云县| 平陆县| 清镇市| 庆阳市| 图们市| 团风县| 郸城县| 翁牛特旗| 上栗县| 惠东县| 哈巴河县|