%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/modules/ |
Current File : //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', '') transport = __salt__['config.get']('transport', '') # 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 # We have to differentiate between RaetKey._check_minions_directories # and Zeromq-Keys. Raet-Keys only have three states while ZeroMQ-keys # have an additional 'denied' state. if transport in ('zeromq', 'tcp'): key_dirs = _check_minions_directories(pki_dir) else: key_dirs = _check_minions_directories_raetkey(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 _check_minions_directories_raetkey(pki_dir): ''' Return the minion keys directory paths. This function is a copy of salt.key.RaetKey._check_minions_directories. ''' accepted = os.path.join(pki_dir, salt.key.RaetKey.ACC) pre = os.path.join(pki_dir, salt.key.RaetKey.PEND) rejected = os.path.join(pki_dir, salt.key.RaetKey.REJ) return accepted, pre, rejected 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