Grains are collected for the operating system, domain name, IP address, kernel, OS type, memory, and many other system properties.
Listing Grains
Available grains can be listed by using the ‘grains.ls’ module:
salt '*' grains.ls
Grains data can be listed by using the ‘grains.items’ module:
salt '*' grains.items
Grains in the Minion Config
Grains can also be statically assigned within the minion configuration file. Just add the option grains and pass options to it:
grains:
roles:
- webserver
- memcache
deployment: datacenter4
cabinet: 13
cab_u: 14-15
Grains in /etc/salt/grains
If you do not want to place your custom static grains in the minion config file, you can also put them in /etc/salt/grains on the minion. ey are configured in the same way as in the above example, only without a top-level grains: key:
roles:
- webserver
- memcache
deployment: datacenter4
cabinet: 13
cab_u: 14-15
Writing Grains
the functions in a grains module must return a Python dict, where the dictionary keys are the names of grains, and each key’s value is that value for that grain.
Custom grains modules should be placed in a subdirectory named _grains located under the file_roots spec- ified by the master config file. e default path would be /srv/salt/_grains. Custom grains modules will be distributed to the minions when state.highstate is run, or by executing the saltutil.sync_grains or saltutil.sync_all functions.
Grains modules are easy to write, and (as noted above) only need to return a dictionary. For example:
def yourfunction():
# initialize a grains dictionary
grains = {}
# Some code for logic that sets grains like
grains['yourcustomgrain'] = True
grains['anothergrain'] = 'somevalue'
return grains
the name of the function does not maer and will not factor into the grains data at all; only the keys/values returned become part of the grains.
When to Use a Custom Grain
Before adding new grains, consider what the data is and remember that grains should (for the most part) be static data.
If the data is something that is likely to change, consider using Pillar or an execution module instead. If it’s a simple set of key/value pairs, pillar is a good match. If compiling the information requires that system commands be run, then puing this information in an execution module is likely a beer idea.
Warning: Customgrainswillnotbeavailableinthetopfileuntilaerthefirsthighstate.Tomakecustomgrains available on a minion’s first highstate, it is recommended to use this example to ensure that the custom grains are synced when the minion starts.
Loading Custom Grains
If you have multiple functions specifying grains that are called from a main function, be sure to prepend grain function names with an underscore. is prevents Salt from including the loaded grains from the grain functions in the final grain data structure. For example, consider this custom grain file:
#!/usr/bin/env python
def _my_custom_grain():
my_grain = {'foo': 'bar', 'hello': 'world'}
return my_grain
def main():
# initialize a grains dictionary
grains = {}
grains['my_grains'] = _my_custom_grain() return grains
the output of this example renders like so:
# salt-call --local grains.items
local:
----------
<Snipped for brevity> my_grains:
----------
foo:
bar
hello:
world
However, if you don’t prepend the my_custom_grain function with an underscore, the function will be rendered twice by Salt in the items output: once for the my_custom_grain call itself, and again when it is called in the main function.
Precedence
Core grains can be overridden by custom grains. As there are several ways of defining custom grains, there is an order of precedence which should be kept in mind when defining them. e order of evaluation is as follows:
1. Core grains.
2. Customgrainsin/etc/salt/grains.
3. Customgrainsin/etc/salt/minion.
4. Customgrainmodulesin_grainsdirectory,syncedtominions.
Each successive evaluation overrides the previous ones, so any grains defined by custom grains modules synced to minions that have the same name as a core grain will override that core grain. Similarly, grains from /etc/salt/minion override both core grains and custom grain modules, and grains in _grains will override any grains of the same name.
Syncing Grains
Syncing grains can be done a number of ways, they are automatically synced when state.highstate is called, or (as noted above) the grains can be manually synced and reloaded by calling the saltutil.sync_grains or saltutil.sync_all functions.
Examples of Grains
the core module in the grains package is where the main grains are loaded by the Salt minion and provides the principal example of how to write grains:
https://github.com/saltstack/salt/blob/develop/salt/grains/core.py