123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- .. _event-system:
- ============
- Event System
- ============
- The Salt Event System is used to fire off events enabling third party
- applications or external processes to react to behavior within Salt.
- The event system uses a publish-subscribe pattern, otherwise know as pub/sub.
- Event Bus
- =========
- The event system is comprised of a two primary components, which make up the
- concept of an Event Bus:
- - The event sockets, which publish events
- - The event library, which can listen to events and send events into the salt system
- Events are published onto the event bus and event bus subscribers listen for the
- published events.
- The event bus is used for both inter-process communication as well as network transport
- in Salt. Inter-process communication is provided through UNIX domain sockets (UDX).
- The Salt Master and each Salt Minion has their own event bus.
- Event types
- ===========
- .. toctree::
- :maxdepth: 2
- master_events
- Listening for Events
- ====================
- Salt's event system is used heavily within Salt and it is also written to
- integrate heavily with existing tooling and scripts. There is a variety of
- ways to consume it.
- From the CLI
- ------------
- The quickest way to watch the event bus is by calling the :py:func:`state.event
- runner <salt.runners.state.event>`:
- .. code-block:: bash
- salt-run state.event pretty=True
- That runner is designed to interact with the event bus from external tools and
- shell scripts. See the documentation for more examples.
- Remotely via the REST API
- -------------------------
- Salt's event bus can be consumed
- :py:class:`salt.netapi.rest_cherrypy.app.Events` as an HTTP stream from
- external tools or services.
- .. code-block:: bash
- curl -SsNk https://salt-api.example.com:8000/events?token=05A3
- From Python
- -----------
- Python scripts can access the event bus only as the same system user that Salt
- is running as.
- The event system is accessed via the event library and can only be accessed
- by the same system user that Salt is running as. To listen to events a
- SaltEvent object needs to be created and then the get_event function needs to
- be run. The SaltEvent object needs to know the location that the Salt Unix
- sockets are kept. In the configuration this is the ``sock_dir`` option. The
- ``sock_dir`` option defaults to "/var/run/salt/master" on most systems.
- The following code will check for a single event:
- .. code-block:: python
- import salt.config
- import salt.utils.event
- opts = salt.config.client_config('/etc/salt/master')
- event = salt.utils.event.get_event(
- 'master',
- sock_dir=opts['sock_dir'],
- transport=opts['transport'],
- opts=opts)
- data = event.get_event()
- Events will also use a "tag". Tags allow for events to be filtered by prefix.
- By default all events will be returned. If only authentication events are
- desired, then pass the tag "salt/auth".
- The ``get_event`` method has a default poll time assigned of 5 seconds. To
- change this time set the "wait" option.
- The following example will only listen for auth events and will wait for 10 seconds
- instead of the default 5.
- .. code-block:: python
- data = event.get_event(wait=10, tag='salt/auth')
- To retrieve the tag as well as the event data, pass ``full=True``:
- .. code-block:: python
- evdata = event.get_event(wait=10, tag='salt/job', full=True)
- tag, data = evdata['tag'], evdata['data']
- Instead of looking for a single event, the ``iter_events`` method can be used to
- make a generator which will continually yield salt events.
- The iter_events method also accepts a tag but not a wait time:
- .. code-block:: python
- for data in event.iter_events(tag='salt/auth'):
- print(data)
- And finally event tags can be globbed, such as they can be in the Reactor,
- using the fnmatch library.
- .. code-block:: python
- import fnmatch
- import salt.config
- import salt.utils.event
- opts = salt.config.client_config('/etc/salt/master')
- sevent = salt.utils.event.get_event(
- 'master',
- sock_dir=opts['sock_dir'],
- transport=opts['transport'],
- opts=opts)
- while True:
- ret = sevent.get_event(full=True)
- if ret is None:
- continue
- if fnmatch.fnmatch(ret['tag'], 'salt/job/*/ret/*'):
- do_something_with_job_return(ret['data'])
- Firing Events
- =============
- It is possible to fire events on either the minion's local bus or to fire
- events intended for the master.
- To fire a local event from the minion on the command line call the
- :py:func:`event.fire <salt.modules.event.fire>` execution function:
- .. code-block:: bash
- salt-call event.fire '{"data": "message to be sent in the event"}' 'tag'
- To fire an event to be sent up to the master from the minion call the
- :py:func:`event.send <salt.modules.event.send>` execution function. Remember
- YAML can be used at the CLI in function arguments:
- .. code-block:: bash
- salt-call event.send 'myco/mytag/success' '{success: True, message: "It works!"}'
- If a process is listening on the minion, it may be useful for a user on the
- master to fire an event to it:
- .. code-block:: python
- # Job on minion
- import salt.utils.event
- event = salt.utils.event.MinionEvent(**__opts__)
- for evdata in event.iter_events(tag='customtag/'):
- return evdata # do your processing here...
- .. code-block:: bash
- salt minionname event.fire '{"data": "message for the minion"}' 'customtag/african/unladen'
- Firing Events from Python
- =========================
- From Salt execution modules
- ---------------------------
- Events can be very useful when writing execution modules, in order to inform
- various processes on the master when a certain task has taken place. This is
- easily done using the normal cross-calling syntax:
- .. code-block:: python
- # /srv/salt/_modules/my_custom_module.py
- def do_something():
- '''
- Do something and fire an event to the master when finished
- CLI Example::
- salt '*' my_custom_module:do_something
- '''
- # do something!
- __salt__['event.send']('myco/my_custom_module/finished', {
- 'finished': True,
- 'message': "The something is finished!",
- })
- From Custom Python Scripts
- --------------------------
- Firing events from custom Python code is quite simple and mirrors how it is
- done at the CLI:
- .. code-block:: python
- import salt.client
- caller = salt.client.Caller()
- caller.sminion.functions['event.send'](
- 'myco/myevent/success',
- {
- 'success': True,
- 'message': "It works!",
- }
- )
|