%PDF- %PDF-
Direktori : /proc/thread-self/root/usr/lib/python2.7/site-packages/salt/client/ssh/wrapper/ |
Current File : //proc/thread-self/root/usr/lib/python2.7/site-packages/salt/client/ssh/wrapper/__init__.py |
# -*- coding: utf-8 -*- ''' The ssh client wrapper system contains the routines that are used to alter how executions are run in the salt-ssh system, this allows for state routines to be easily rewritten to execute in a way that makes them do the same tasks as ZeroMQ salt, but via ssh. ''' # Import python libs from __future__ import absolute_import, print_function import copy # Import salt libs import salt.loader import salt.utils.data import salt.utils.json import salt.client.ssh # Import 3rd-party libs from salt.ext import six class FunctionWrapper(object): ''' Create an object that acts like the salt function dict and makes function calls remotely via the SSH shell system ''' def __init__( self, opts, id_, host, wfuncs=None, mods=None, fsclient=None, cmd_prefix=None, aliases=None, minion_opts=None, **kwargs): super(FunctionWrapper, self).__init__() self.cmd_prefix = cmd_prefix self.wfuncs = wfuncs if isinstance(wfuncs, dict) else {} self.opts = opts self.mods = mods if isinstance(mods, dict) else {} self.kwargs = {'id_': id_, 'host': host} self.fsclient = fsclient self.kwargs.update(kwargs) self.aliases = aliases if self.aliases is None: self.aliases = {} self.minion_opts = minion_opts def __contains__(self, key): ''' We need to implement a __contains__ method, othwerwise when someone does a contains comparison python assumes this is a sequence, and does __getitem__ keys 0 and up until IndexError ''' try: self[key] # pylint: disable=W0104 return True except KeyError: return False def __getitem__(self, cmd): ''' Return the function call to simulate the salt local lookup system ''' if '.' not in cmd and not self.cmd_prefix: # Form of salt.cmd.run in Jinja -- it's expecting a subdictionary # containing only 'cmd' module calls, in that case. Create a new # FunctionWrapper which contains the prefix 'cmd' (again, for the # salt.cmd.run example) kwargs = copy.deepcopy(self.kwargs) id_ = kwargs.pop('id_') host = kwargs.pop('host') return FunctionWrapper(self.opts, id_, host, wfuncs=self.wfuncs, mods=self.mods, fsclient=self.fsclient, cmd_prefix=cmd, aliases=self.aliases, minion_opts=self.minion_opts, **kwargs) if self.cmd_prefix: # We're in an inner FunctionWrapper as created by the code block # above. Reconstruct the original cmd in the form 'cmd.run' and # then evaluate as normal cmd = '{0}.{1}'.format(self.cmd_prefix, cmd) if cmd in self.wfuncs: return self.wfuncs[cmd] if cmd in self.aliases: return self.aliases[cmd] def caller(*args, **kwargs): ''' The remote execution function ''' argv = [cmd] argv.extend([salt.utils.json.dumps(arg) for arg in args]) argv.extend( ['{0}={1}'.format(salt.utils.stringutils.to_str(key), salt.utils.json.dumps(val)) for key, val in six.iteritems(kwargs)] ) single = salt.client.ssh.Single( self.opts, argv, mods=self.mods, disable_wipe=True, fsclient=self.fsclient, minion_opts=self.minion_opts, **self.kwargs ) stdout, stderr, retcode = single.cmd_block() if stderr.count('Permission Denied'): return {'_error': 'Permission Denied', 'stdout': stdout, 'stderr': stderr, 'retcode': retcode} try: ret = salt.utils.json.loads(stdout) if len(ret) < 2 and 'local' in ret: ret = ret['local'] ret = ret.get('return', {}) except ValueError: ret = {'_error': 'Failed to return clean data', 'stderr': stderr, 'stdout': stdout, 'retcode': retcode} return ret return caller def __setitem__(self, cmd, value): ''' Set aliases for functions ''' if '.' not in cmd and not self.cmd_prefix: # Form of salt.cmd.run in Jinja -- it's expecting a subdictionary # containing only 'cmd' module calls, in that case. We don't # support assigning directly to prefixes in this way raise KeyError('Cannot assign to module key {0} in the ' 'FunctionWrapper'.format(cmd)) if self.cmd_prefix: # We're in an inner FunctionWrapper as created by the first code # block in __getitem__. Reconstruct the original cmd in the form # 'cmd.run' and then evaluate as normal cmd = '{0}.{1}'.format(self.cmd_prefix, cmd) if cmd in self.wfuncs: self.wfuncs[cmd] = value # Here was assume `value` is a `caller` function from __getitem__. # We save it as an alias and then can return it when referenced # later in __getitem__ self.aliases[cmd] = value def get(self, cmd, default): ''' Mirrors behavior of dict.get ''' if cmd in self: return self[cmd] else: return default