- Extending SaltStack
- Joseph Hall
- 781字
- 2021-07-16 12:42:19
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_)
- Hadoop 2.x Administration Cookbook
- 計算機控制技術
- Bayesian Analysis with Python
- 精通LabVIEW程序設計
- 網絡存儲·數據備份與還原
- INSTANT Puppet 3 Starter
- Spark大數據商業實戰三部曲:內核解密|商業案例|性能調優
- 網站規劃與網頁設計
- Moodle 2.0 Course Conversion(Second Edition)
- 項目實踐精解:C#核心技術應用開發
- 工業機器人應用系統三維建模
- Appcelerator Titanium Smartphone App Development Cookbook(Second Edition)
- 多傳感器數據智能融合理論與應用
- Data Science with Python
- 亮劍.NET:圖解ASP.NET網站開發實戰