File: //proc/self/root/usr/lib/python2.7/site-packages/salt/modules/minion.py
# -*- coding: utf-8 -*-
'''
Module to provide information about minions
'''
from __future__ import absolute_import, print_function, unicode_literals
# Import Python libs
import os
import sys
import time
# Import Salt libs
import salt.utils.data
import salt.key
# Import third party libs
from salt.ext import six
from salt.ext.six.moves import range
# Don't shadow built-ins.
__func_alias__ = {
'list_': 'list'
}
def list_():
'''
Return a list of accepted, denied, unaccepted and rejected keys.
This is the same output as `salt-key -L`
CLI Example:
.. code-block:: bash
salt 'master' minion.list
'''
pki_dir = __salt__['config.get']('pki_dir', '')
# We have to replace the minion/master directories
pki_dir = pki_dir.replace('minion', 'master')
# The source code below is (nearly) a copy of salt.key.Key.list_keys
key_dirs = _check_minions_directories(pki_dir)
ret = {}
for dir_ in key_dirs:
ret[os.path.basename(dir_)] = []
try:
for fn_ in salt.utils.data.sorted_ignorecase(os.listdir(dir_)):
if not fn_.startswith('.'):
if os.path.isfile(os.path.join(dir_, fn_)):
ret[os.path.basename(dir_)].append(fn_)
except (OSError, IOError):
# key dir kind is not created yet, just skip
continue
return ret
def _check_minions_directories(pki_dir):
'''
Return the minion keys directory paths.
This function is a copy of salt.key.Key._check_minions_directories.
'''
minions_accepted = os.path.join(pki_dir, salt.key.Key.ACC)
minions_pre = os.path.join(pki_dir, salt.key.Key.PEND)
minions_rejected = os.path.join(pki_dir, salt.key.Key.REJ)
minions_denied = os.path.join(pki_dir, salt.key.Key.DEN)
return minions_accepted, minions_pre, minions_rejected, minions_denied
def kill(timeout=15):
'''
Kill the salt minion.
timeout
int seconds to wait for the minion to die.
If you have a monitor that restarts ``salt-minion`` when it dies then this is
a great way to restart after a minion upgrade.
CLI example::
>$ salt minion[12] minion.kill
minion1:
----------
killed:
7874
retcode:
0
minion2:
----------
killed:
29071
retcode:
0
The result of the salt command shows the process ID of the minions and the
results of a kill signal to the minion in as the ``retcode`` value: ``0``
is success, anything else is a failure.
'''
ret = {
'killed': None,
'retcode': 1,
}
comment = []
pid = __grains__.get('pid')
if not pid:
comment.append('Unable to find "pid" in grains')
ret['retcode'] = salt.defaults.exitcodes.EX_SOFTWARE
else:
if 'ps.kill_pid' not in __salt__:
comment.append('Missing command: ps.kill_pid')
ret['retcode'] = salt.defaults.exitcodes.EX_SOFTWARE
else:
# The retcode status comes from the first kill signal
ret['retcode'] = int(not __salt__['ps.kill_pid'](pid))
# If the signal was successfully delivered then wait for the
# process to die - check by sending signals until signal delivery
# fails.
if ret['retcode']:
comment.append('ps.kill_pid failed')
else:
for _ in range(timeout):
time.sleep(1)
signaled = __salt__['ps.kill_pid'](pid)
if not signaled:
ret['killed'] = pid
break
else:
# The process did not exit before the timeout
comment.append('Timed out waiting for minion to exit')
ret['retcode'] = salt.defaults.exitcodes.EX_TEMPFAIL
if comment:
ret['comment'] = comment
return ret
def restart():
'''
Kill and restart the salt minion.
The configuration key ``minion_restart_command`` is an argv list for the
command to restart the minion. If ``minion_restart_command`` is not
specified or empty then the ``argv`` of the current process will be used.
if the configuration value ``minion_restart_command`` is not set and the
``-d`` (daemonize) argument is missing from ``argv`` then the minion
*will* be killed but will *not* be restarted and will require the parent
process to perform the restart. This behavior is intended for managed
salt minion processes.
CLI example::
>$ salt minion[12] minion.restart
minion1:
----------
comment:
- Restart using process argv:
- /home/omniture/install/bin/salt-minion
- -d
- -c
- /home/omniture/install/etc/salt
killed:
10070
restart:
----------
stderr:
stdout:
retcode:
0
minion2:
----------
comment:
- Using configuration minion_restart_command:
- /home/omniture/install/bin/salt-minion
- --not-an-option
- -d
- -c
- /home/omniture/install/etc/salt
- Restart failed
killed:
10896
restart:
----------
stderr:
Usage: salt-minion
salt-minion: error: no such option: --not-an-option
stdout:
retcode:
64
The result of the command shows the process ID of ``minion1`` that is
shutdown (killed) and the results of the restart. If there is a failure
in the restart it will be reflected in a non-zero ``retcode`` and possibly
output in the ``stderr`` and/or ``stdout`` values along with addition
information in the ``comment`` field as is demonstrated with ``minion2``.
'''
should_kill = True
should_restart = True
comment = []
ret = {
'killed': None,
'restart': {},
'retcode': 0,
}
restart_cmd = __salt__['config.get']('minion_restart_command')
if restart_cmd:
comment.append('Using configuration minion_restart_command:')
comment.extend([' {0}'.format(arg) for arg in restart_cmd])
else:
if '-d' in sys.argv:
restart_cmd = sys.argv
comment.append('Restart using process argv:')
comment.extend([' {0}'.format(arg) for arg in restart_cmd])
else:
should_restart = False
comment.append('Not running in daemon mode - will not restart process after killing')
if should_kill:
ret.update(kill())
if 'comment' in ret and ret['comment']:
if isinstance(ret['comment'], six.string_types):
comment.append(ret['comment'])
else:
comment.extend(ret['comment'])
if ret['retcode']:
comment.append('Kill failed - not restarting')
should_restart = False
if should_restart:
ret['restart'] = __salt__['cmd.run_all'](restart_cmd, env=os.environ)
# Do not want to mislead users to think that the returned PID from
# cmd.run_all() is the PID of the new salt minion - just delete the
# returned PID.
if 'pid' in ret['restart']:
del ret['restart']['pid']
if ret['restart'].get('retcode', None):
comment.append('Restart failed')
ret['retcode'] = ret['restart']['retcode']
if 'retcode' in ret['restart']:
# Just want a single retcode
del ret['restart']['retcode']
if comment:
ret['comment'] = comment
return ret