File: //proc/self/root/usr/lib/python2.7/site-packages/salt/client/ssh/client.py
# -*- coding: utf-8 -*-
# Import Python libs
from __future__ import absolute_import, print_function, unicode_literals
import os
import copy
import logging
import random
# Import Salt libs
import salt.config
import salt.utils.args
import salt.syspaths as syspaths
from salt.exceptions import SaltClientError # Temporary
log = logging.getLogger(__name__)
class SSHClient(object):
'''
Create a client object for executing routines via the salt-ssh backend
.. versionadded:: 2015.5.0
'''
def __init__(self,
c_path=os.path.join(syspaths.CONFIG_DIR, 'master'),
mopts=None,
disable_custom_roster=False):
if mopts:
self.opts = mopts
else:
if os.path.isdir(c_path):
log.warning(
'%s expects a file path not a directory path(%s) to '
'its \'c_path\' keyword argument',
self.__class__.__name__, c_path
)
self.opts = salt.config.client_config(c_path)
# Salt API should never offer a custom roster!
self.opts['__disable_custom_roster'] = disable_custom_roster
def _prep_ssh(
self,
tgt,
fun,
arg=(),
timeout=None,
tgt_type='glob',
kwarg=None,
**kwargs):
'''
Prepare the arguments
'''
opts = copy.deepcopy(self.opts)
opts.update(kwargs)
if timeout:
opts['timeout'] = timeout
arg = salt.utils.args.condition_input(arg, kwarg)
opts['argv'] = [fun] + arg
opts['selected_target_option'] = tgt_type
opts['tgt'] = tgt
opts['arg'] = arg
return salt.client.ssh.SSH(opts)
def cmd_iter(
self,
tgt,
fun,
arg=(),
timeout=None,
tgt_type='glob',
ret='',
kwarg=None,
**kwargs):
'''
Execute a single command via the salt-ssh subsystem and return a
generator
.. versionadded:: 2015.5.0
'''
ssh = self._prep_ssh(
tgt,
fun,
arg,
timeout,
tgt_type,
kwarg,
**kwargs)
for ret in ssh.run_iter(jid=kwargs.get('jid', None)):
yield ret
def cmd(self,
tgt,
fun,
arg=(),
timeout=None,
tgt_type='glob',
kwarg=None,
**kwargs):
'''
Execute a single command via the salt-ssh subsystem and return all
routines at once
.. versionadded:: 2015.5.0
'''
ssh = self._prep_ssh(
tgt,
fun,
arg,
timeout,
tgt_type,
kwarg,
**kwargs)
final = {}
for ret in ssh.run_iter(jid=kwargs.get('jid', None)):
final.update(ret)
return final
def cmd_sync(self, low):
'''
Execute a salt-ssh call synchronously.
.. versionadded:: 2015.5.0
WARNING: Eauth is **NOT** respected
.. code-block:: python
client.cmd_sync({
'tgt': 'silver',
'fun': 'test.ping',
'arg': (),
'tgt_type'='glob',
'kwarg'={}
})
{'silver': {'fun_args': [], 'jid': '20141202152721523072', 'return': True, 'retcode': 0, 'success': True, 'fun': 'test.ping', 'id': 'silver'}}
'''
kwargs = copy.deepcopy(low)
for ignore in ['tgt', 'fun', 'arg', 'timeout', 'tgt_type', 'kwarg']:
if ignore in kwargs:
del kwargs[ignore]
return self.cmd(low['tgt'],
low['fun'],
low.get('arg', []),
low.get('timeout'),
low.get('tgt_type'),
low.get('kwarg'),
**kwargs)
def cmd_async(self, low, timeout=None):
'''
Execute aa salt-ssh asynchronously
WARNING: Eauth is **NOT** respected
.. code-block:: python
client.cmd_sync({
'tgt': 'silver',
'fun': 'test.ping',
'arg': (),
'tgt_type'='glob',
'kwarg'={}
})
{'silver': {'fun_args': [], 'jid': '20141202152721523072', 'return': True, 'retcode': 0, 'success': True, 'fun': 'test.ping', 'id': 'silver'}}
'''
# TODO Not implemented
raise SaltClientError
def cmd_subset(
self,
tgt,
fun,
arg=(),
timeout=None,
tgt_type='glob',
ret='',
kwarg=None,
sub=3,
**kwargs):
'''
Execute a command on a random subset of the targeted systems
The function signature is the same as :py:meth:`cmd` with the
following exceptions.
:param sub: The number of systems to execute on
.. code-block:: python
>>> import salt.client.ssh.client
>>> sshclient= salt.client.ssh.client.SSHClient()
>>> sshclient.cmd_subset('*', 'test.ping', sub=1)
{'jerry': True}
.. versionadded:: 2017.7.0
'''
minion_ret = self.cmd(tgt,
'sys.list_functions',
tgt_type=tgt_type,
**kwargs)
minions = list(minion_ret)
random.shuffle(minions)
f_tgt = []
for minion in minions:
if fun in minion_ret[minion]['return']:
f_tgt.append(minion)
if len(f_tgt) >= sub:
break
return self.cmd_iter(f_tgt, fun, arg, timeout, tgt_type='list', ret=ret, kwarg=kwarg, **kwargs)