%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/transport/ |
Current File : //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', {})