1
0

index.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. .. _returners:
  2. =========
  3. Returners
  4. =========
  5. By default the return values of the commands sent to the Salt minions are
  6. returned to the Salt master, however anything at all can be done with the results
  7. data.
  8. By using a Salt returner, results data can be redirected to external data-stores
  9. for analysis and archival.
  10. Returners pull their configuration values from the Salt minions. Returners are only
  11. configured once, which is generally at load time.
  12. The returner interface allows the return data to be sent to any system that
  13. can receive data. This means that return data can be sent to a Redis server,
  14. a MongoDB server, a MySQL server, or any system.
  15. .. seealso:: :ref:`Full list of builtin returners <all-salt.returners>`
  16. Using Returners
  17. ===============
  18. All Salt commands will return the command data back to the master. Specifying
  19. returners will ensure that the data is _also_ sent to the specified returner
  20. interfaces.
  21. Specifying what returners to use is done when the command is invoked:
  22. .. code-block:: bash
  23. salt '*' test.version --return redis_return
  24. This command will ensure that the redis_return returner is used.
  25. It is also possible to specify multiple returners:
  26. .. code-block:: bash
  27. salt '*' test.version --return mongo_return,redis_return,cassandra_return
  28. In this scenario all three returners will be called and the data from the
  29. test.version command will be sent out to the three named returners.
  30. Writing a Returner
  31. ==================
  32. Returners are Salt modules that allow the redirection of results data to targets other than the Salt Master.
  33. Returners Are Easy To Write!
  34. ----------------------------
  35. Writing a Salt returner is straightforward.
  36. A returner is a Python module containing at minimum a ``returner`` function.
  37. Other optional functions can be included to add support for
  38. :conf_master:`master_job_cache`, :ref:`external-job-cache`, and `Event Returners`_.
  39. ``returner``
  40. The ``returner`` function must accept a single argument. The argument
  41. contains return data from the called minion function. If the minion
  42. function ``test.version`` is called, the value of the argument will be a
  43. dictionary. Run the following command from a Salt master to get a sample
  44. of the dictionary:
  45. .. code-block:: bash
  46. salt-call --local --metadata test.version --out=pprint
  47. .. code-block:: python
  48. import redis
  49. import salt.utils.json
  50. def returner(ret):
  51. """
  52. Return information to a redis server
  53. """
  54. # Get a redis connection
  55. serv = redis.Redis(host="redis-serv.example.com", port=6379, db="0")
  56. serv.sadd("%(id)s:jobs" % ret, ret["jid"])
  57. serv.set("%(jid)s:%(id)s" % ret, salt.utils.json.dumps(ret["return"]))
  58. serv.sadd("jobs", ret["jid"])
  59. serv.sadd(ret["jid"], ret["id"])
  60. The above example of a returner set to send the data to a Redis server
  61. serializes the data as JSON and sets it in redis.
  62. Using Custom Returner Modules
  63. -----------------------------
  64. Place custom returners in a ``_returners/`` directory within the
  65. :conf_master:`file_roots` specified by the master config file.
  66. Custom returners are distributed when any of the following are called:
  67. - :mod:`state.apply <salt.modules.state.apply_>`
  68. - :mod:`saltutil.sync_returners <salt.modules.saltutil.sync_returners>`
  69. - :mod:`saltutil.sync_all <salt.modules.saltutil.sync_all>`
  70. Any custom returners which have been synced to a minion that are named the
  71. same as one of Salt's default set of returners will take the place of the
  72. default returner with the same name.
  73. Naming the Returner
  74. -------------------
  75. Note that a returner's default name is its filename (i.e. ``foo.py`` becomes
  76. returner ``foo``), but that its name can be overridden by using a
  77. :ref:`__virtual__ function <virtual-modules>`. A good example of this can be
  78. found in the `redis`_ returner, which is named ``redis_return.py`` but is
  79. loaded as simply ``redis``:
  80. .. code-block:: python
  81. try:
  82. import redis
  83. HAS_REDIS = True
  84. except ImportError:
  85. HAS_REDIS = False
  86. __virtualname__ = "redis"
  87. def __virtual__():
  88. if not HAS_REDIS:
  89. return False
  90. return __virtualname__
  91. Master Job Cache Support
  92. ------------------------
  93. :conf_master:`master_job_cache`, :ref:`external-job-cache`, and `Event Returners`_.
  94. Salt's :conf_master:`master_job_cache` allows returners to be used as a pluggable
  95. replacement for the :ref:`default_job_cache`. In order to do so, a returner
  96. must implement the following functions:
  97. .. note::
  98. The code samples contained in this section were taken from the cassandra_cql
  99. returner.
  100. ``prep_jid``
  101. Ensures that job ids (jid) don't collide, unless passed_jid is provided.
  102. ``nocache`` is an optional boolean that indicates if return data
  103. should be cached. ``passed_jid`` is a caller provided jid which should be
  104. returned unconditionally.
  105. .. code-block:: python
  106. def prep_jid(nocache, passed_jid=None): # pylint: disable=unused-argument
  107. """
  108. Do any work necessary to prepare a JID, including sending a custom id
  109. """
  110. return passed_jid if passed_jid is not None else salt.utils.jid.gen_jid()
  111. ``save_load``
  112. Save job information. The ``jid`` is generated by ``prep_jid`` and should
  113. be considered a unique identifier for the job. The jid, for example, could
  114. be used as the primary/unique key in a database. The ``load`` is what is
  115. returned to a Salt master by a minion. ``minions`` is a list of minions
  116. that the job was run against. The following code example stores the load as
  117. a JSON string in the salt.jids table.
  118. .. code-block:: python
  119. import salt.utils.json
  120. def save_load(jid, load, minions=None):
  121. """
  122. Save the load to the specified jid id
  123. """
  124. query = """INSERT INTO salt.jids (
  125. jid, load
  126. ) VALUES (
  127. '{0}', '{1}'
  128. );""".format(
  129. jid, salt.utils.json.dumps(load)
  130. )
  131. # cassandra_cql.cql_query may raise a CommandExecutionError
  132. try:
  133. __salt__["cassandra_cql.cql_query"](query)
  134. except CommandExecutionError:
  135. log.critical("Could not save load in jids table.")
  136. raise
  137. except Exception as e:
  138. log.critical("Unexpected error while inserting into jids: {0}".format(e))
  139. raise
  140. ``get_load``
  141. must accept a job id (jid) and return the job load stored by ``save_load``,
  142. or an empty dictionary when not found.
  143. .. code-block:: python
  144. def get_load(jid):
  145. """
  146. Return the load data that marks a specified jid
  147. """
  148. query = """SELECT load FROM salt.jids WHERE jid = '{0}';""".format(jid)
  149. ret = {}
  150. # cassandra_cql.cql_query may raise a CommandExecutionError
  151. try:
  152. data = __salt__["cassandra_cql.cql_query"](query)
  153. if data:
  154. load = data[0].get("load")
  155. if load:
  156. ret = json.loads(load)
  157. except CommandExecutionError:
  158. log.critical("Could not get load from jids table.")
  159. raise
  160. except Exception as e:
  161. log.critical(
  162. """Unexpected error while getting load from
  163. jids: {0}""".format(
  164. str(e)
  165. )
  166. )
  167. raise
  168. return ret
  169. External Job Cache Support
  170. --------------------------
  171. Salt's :ref:`external-job-cache` extends the :conf_master:`master_job_cache`. External
  172. Job Cache support requires the following functions in addition to what is
  173. required for Master Job Cache support:
  174. ``get_jid``
  175. Return a dictionary containing the information (load) returned by each
  176. minion when the specified job id was executed.
  177. Sample:
  178. .. code-block:: JSON
  179. {
  180. "local": {
  181. "master_minion": {
  182. "fun_args": [],
  183. "jid": "20150330121011408195",
  184. "return": "2018.3.4",
  185. "retcode": 0,
  186. "success": true,
  187. "cmd": "_return",
  188. "_stamp": "2015-03-30T12:10:12.708663",
  189. "fun": "test.version",
  190. "id": "master_minion"
  191. }
  192. }
  193. }
  194. ``get_fun``
  195. Return a dictionary of minions that called a given Salt function as their
  196. last function call.
  197. Sample:
  198. .. code-block:: JSON
  199. {
  200. "local": {
  201. "minion1": "test.version",
  202. "minion3": "test.version",
  203. "minion2": "test.version"
  204. }
  205. }
  206. ``get_jids``
  207. Return a list of all job ids.
  208. Sample:
  209. .. code-block:: JSON
  210. {
  211. "local": [
  212. "20150330121011408195",
  213. "20150330195922139916"
  214. ]
  215. }
  216. ``get_minions``
  217. Returns a list of minions
  218. Sample:
  219. .. code-block:: JSON
  220. {
  221. "local": [
  222. "minion3",
  223. "minion2",
  224. "minion1",
  225. "master_minion"
  226. ]
  227. }
  228. Please refer to one or more of the existing returners (i.e. mysql,
  229. cassandra_cql) if you need further clarification.
  230. Event Support
  231. -------------
  232. An ``event_return`` function must be added to the returner module to allow
  233. events to be logged from a master via the returner. A list of events are passed
  234. to the function by the master.
  235. The following example was taken from the MySQL returner. In this example, each
  236. event is inserted into the salt_events table keyed on the event tag. The tag
  237. contains the jid and therefore is guaranteed to be unique.
  238. .. code-block:: python
  239. import salt.utils.json
  240. def event_return(events):
  241. """
  242. Return event to mysql server
  243. Requires that configuration be enabled via 'event_return'
  244. option in master config.
  245. """
  246. with _get_serv(events, commit=True) as cur:
  247. for event in events:
  248. tag = event.get("tag", "")
  249. data = event.get("data", "")
  250. sql = """INSERT INTO `salt_events` (`tag`, `data`, `master_id` )
  251. VALUES (%s, %s, %s)"""
  252. cur.execute(sql, (tag, salt.utils.json.dumps(data), __opts__["id"]))
  253. Testing the Returner
  254. --------------------
  255. The ``returner``, ``prep_jid``, ``save_load``, ``get_load``, and
  256. ``event_return`` functions can be tested by configuring the
  257. :conf_master:`master_job_cache` and `Event Returners`_ in the master config
  258. file and submitting a job to ``test.version`` each minion from the master.
  259. Once you have successfully exercised the Master Job Cache functions, test the
  260. External Job Cache functions using the ``ret`` execution module.
  261. .. code-block:: bash
  262. salt-call ret.get_jids cassandra_cql --output=json
  263. salt-call ret.get_fun cassandra_cql test.version --output=json
  264. salt-call ret.get_minions cassandra_cql --output=json
  265. salt-call ret.get_jid cassandra_cql 20150330121011408195 --output=json
  266. Event Returners
  267. ===============
  268. For maximum visibility into the history of events across a Salt
  269. infrastructure, all events seen by a salt master may be logged to one or
  270. more returners.
  271. To enable event logging, set the ``event_return`` configuration option in the
  272. master config to the returner(s) which should be designated as the handler
  273. for event returns.
  274. .. note::
  275. Not all returners support event returns. Verify a returner has an
  276. ``event_return()`` function before using.
  277. .. note::
  278. On larger installations, many hundreds of events may be generated on a
  279. busy master every second. Be certain to closely monitor the storage of
  280. a given returner as Salt can easily overwhelm an underpowered server
  281. with thousands of returns.
  282. Full List of Returners
  283. ======================
  284. .. toctree::
  285. all/index
  286. .. _`redis`: https://github.com/saltstack/salt/tree/|repo_primary_branch|/salt/returners/redis_return.py