%PDF- %PDF-
| Direktori : /proc/self/root/proc/self/root/usr/lib/python2.7/site-packages/salt/transport/ |
| Current File : //proc/self/root/proc/self/root/usr/lib/python2.7/site-packages/salt/transport/raet.py |
# -*- coding: utf-8 -*-
'''
RAET transport classes
'''
from __future__ import absolute_import, print_function, unicode_literals
import time
# Import Salt Libs
import logging
import salt.utils.kinds as kinds
from salt.transport.client import ReqChannel
log = logging.getLogger(__name__)
try:
from raet import raeting, nacling
from raet.lane.stacking import LaneStack
from raet.lane.yarding import RemoteYard
except (ImportError, OSError):
# Don't die on missing transport libs since only one transport is required
pass
# Module globals for default LaneStack. Because RAETReqChannels are created on demand
# they do not have access to the master estate that motivated their creation
# Also in Raet a LaneStack can be shared shared by all channels in a given jobber
# For these reasons module globals are used to setup a shared jobber_stack as
# well has routing information for the master that motivated the jobber
# when a channel is not used in a jobber context then a LaneStack is created
# on demand.
jobber_stack = None # module global that holds raet jobber LaneStack
jobber_rxMsgs = {} # dict of deques one for each RAETReqChannel for the jobber
jobber_estate_name = None # module global of motivating master estate name
jobber_yard_name = None # module global of motivating master yard name
class RAETReqChannel(ReqChannel):
'''
Build the communication framework to communicate over the local process
uxd socket and send messages forwarded to the master. then wait for the
relative return message.
Two use cases:
mininion to master communication, normal use case
Minion is communicating via yard through minion Road to master
The destination route needs the estate name of the associated master
master call via runner, special use case
In the special case the master call external process is communicating
via a yard with the master manor yard
The destination route estate is None to indicate local estate
The difference between the two is how the destination route
is assigned.
'''
def __init__(self, opts, usage=None, **kwargs):
self.opts = opts
self.ttype = 'raet'
if usage == 'master_call': # runner.py master_call
self.dst = (None, None, 'local_cmd')
else: # everything else minion to master including salt-call
self.dst = (jobber_estate_name or None,
jobber_yard_name or None,
'remote_cmd')
self.stack = None
self.ryn = 'manor' # remote yard name
def __prep_stack(self):
'''
Prepare the stack objects
'''
global jobber_stack
if not self.stack:
if jobber_stack:
self.stack = jobber_stack
else:
self.stack = jobber_stack = self._setup_stack(ryn=self.ryn)
log.debug("RAETReqChannel Using Jobber Stack at = %s\n", self.stack.ha)
def _setup_stack(self, ryn='manor'):
'''
Setup and return the LaneStack and Yard used by by channel when global
not already setup such as in salt-call to communicate to-from the minion
'''
role = self.opts.get('id')
if not role:
emsg = ("Missing role(\'id\') required to setup RAETReqChannel.")
log.error(emsg + "\n")
raise ValueError(emsg)
kind = self.opts.get('__role') # application kind 'master', 'minion', etc
if kind not in kinds.APPL_KINDS:
emsg = ("Invalid application kind = '{0}' for RAETReqChannel.".format(kind))
log.error(emsg + "\n")
raise ValueError(emsg)
if kind in [kinds.APPL_KIND_NAMES[kinds.applKinds.master],
kinds.APPL_KIND_NAMES[kinds.applKinds.syndic]]:
lanename = 'master'
elif kind in [kinds.APPL_KIND_NAMES[kinds.applKinds.minion],
kinds.APPL_KIND_NAMES[kinds.applKinds.caller]]:
lanename = "{0}_{1}".format(role, kind)
else:
emsg = ("Unsupported application kind '{0}' for RAETReqChannel.".format(kind))
log.error(emsg + '\n')
raise ValueError(emsg)
name = 'channel' + nacling.uuid(size=18)
stack = LaneStack(name=name,
lanename=lanename,
sockdirpath=self.opts['sock_dir'])
stack.Pk = raeting.PackKind.pack
stack.addRemote(RemoteYard(stack=stack,
name=ryn,
lanename=lanename,
dirpath=self.opts['sock_dir']))
log.debug("Created Channel Jobber Stack %s\n", stack.name)
return stack
def crypted_transfer_decode_dictentry(self, load, dictkey=None, tries=3, timeout=60):
'''
We don't need to do the crypted_transfer_decode_dictentry routine for
raet, just wrap send.
'''
return self.send(load, tries, timeout)
def send(self, load, tries=3, timeout=60, raw=False):
'''
Send a message load and wait for a relative reply
One shot wonder
'''
self.__prep_stack()
tried = 1
start = time.time()
track = nacling.uuid(18)
src = (None, self.stack.local.name, track)
self.route = {'src': src, 'dst': self.dst}
msg = {'route': self.route, 'load': load}
self.stack.transmit(msg, self.stack.nameRemotes[self.ryn].uid)
while track not in jobber_rxMsgs:
self.stack.serviceAll()
while self.stack.rxMsgs:
msg, sender = self.stack.rxMsgs.popleft()
jobber_rxMsgs[msg['route']['dst'][2]] = msg
continue
if track in jobber_rxMsgs:
break
if time.time() - start > timeout:
if tried >= tries:
raise ValueError("Message send timed out after '{0} * {1}'"
" secs. route = {2} track = {3} load={4}".format(tries,
timeout,
self.route,
track,
load))
self.stack.transmit(msg, self.stack.nameRemotes['manor'].uid)
tried += 1
time.sleep(0.01)
return jobber_rxMsgs.pop(track).get('return', {})