def _return_pub(self, msg, ret): ''' Send the return data back via the uxd socket ''' ret_stack = LaneStack( lanename=self.opts['id'], yid=ret['jid'], sockdirpath=self.opts['sock_dir'], dirpath=self.opts['cachedir']) ret_stack.Pk = raeting.packKinds.pack main_yard = RemoteYard( yid=0, prefix=self.opts['id'], dirpath=self.opts['sock_dir'] ) ret_stack.addRemote(main_yard) route = {'src': (self.opts['id'], ret_stack.local.name, 'jid_ret'), 'dst': (msg['route']['src'][0], None, 'remote_cmd')} ret['cmd'] = '_return' ret['id'] = self.opts['id'] try: oput = self.modules.value[ret['fun']].__outputter__ except (KeyError, AttributeError, TypeError): pass else: if isinstance(oput, str): ret['out'] = oput msg = {'route': route, 'load': ret} ret_stack.transmit(msg, ret_stack.uids.get('yard0')) ret_stack.serviceAll()
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 {0}\n".format(stack.name)) return stack
def action(self): self.stats_req.value = deque() # Create event stack name = 'event' + nacling.uuid(size=18) lanename = self.lane_stack.value.local.lanename sock_dir = self.lane_stack.value.local.dirpath ryn = 'manor' console.terse("Create stack: name = {0}, lanename = {1}, sock_dir = {2}\n". format(name, lanename, sock_dir)) stack = LaneStack( name=name, lanename=lanename, sockdirpath=sock_dir) stack.addRemote(RemoteYard(stack=stack, lanename=lanename, name=ryn, dirpath=sock_dir)) self.event_stack.value = stack route = {'dst': (None, ryn, 'stats_req'), 'src': (None, stack.local.name, None)} msg = {'route': route} stack.transmit(msg, stack.nameRemotes[ryn].uid) serviceLanes([stack, self.lane_stack.value])
def pub(self, tgt, fun, arg=(), expr_form='glob', ret='', jid='', timeout=5, **kwargs): ''' Publish the command! ''' payload_kwargs = self._prep_pub( tgt, fun, arg=arg, expr_form=expr_form, ret=ret, jid=jid, timeout=timeout, **kwargs) kind = self.opts['__role'] if kind == 'master': lanename = 'master' # self.opts.value.get('id', self.main.data.lanename) else: # workers currently are only supported for masters emsg = ("Invalid application kind '{0}' for client.".format(kind)) log.error(emsg + '\n') raise ValueError(emsg) name = 'client' + nacling.uuid(size=18) stack = LaneStack( name=name, lanename=lanename, sockdirpath=self.opts['sock_dir']) stack.Pk = raeting.packKinds.pack router_yard = RemoteYard( stack=stack, lanename=lanename, name='manor', dirpath=self.opts['sock_dir']) stack.addRemote(router_yard) route = {'dst': (None, router_yard.name, 'local_cmd'), 'src': (None, stack.local.name, None)} msg = {'route': route, 'load': payload_kwargs} stack.transmit(msg) stack.serviceAll() while True: time.sleep(0.01) stack.serviceAll() while stack.rxMsgs: msg, sender = stack.rxMsgs.popleft() ret = msg.get('return', {}) if 'ret' in ret: stack.server.close() return ret['ret'] stack.server.close() return ret
def pub(self, tgt, fun, arg=(), expr_form='glob', ret='', jid='', timeout=5, **kwargs): ''' Publish the command! ''' payload_kwargs = self._prep_pub( tgt, fun, arg=arg, expr_form=expr_form, ret=ret, jid=jid, timeout=timeout, **kwargs) yid = nacling.uuid(size=18) stack = LaneStack( name=('client' + yid), yid=yid, lanename='master', sockdirpath=self.opts['sock_dir']) stack.Pk = raeting.packKinds.pack router_yard = RemoteYard( stack=stack, lanename='master', yid=0, name='manor', dirpath=self.opts['sock_dir']) stack.addRemote(router_yard) route = {'dst': (None, router_yard.name, 'local_cmd'), 'src': (None, stack.local.name, None)} msg = {'route': route, 'load': payload_kwargs} stack.transmit(msg) stack.serviceAll() while True: time.sleep(0.01) stack.serviceAll() while stack.rxMsgs: msg, sender = stack.rxMsgs.popleft() ret = msg.get('return', {}) if 'ret' in ret: stack.server.close() return ret['ret'] stack.server.close() return ret
class RAETChannel(Channel): ''' 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. ''' def __init__(self, opts, **kwargs): self.opts = opts self.ttype = 'raet' self.__prep_stack() def __prep_stack(self): ''' Prepare the stack objects ''' self.stack = LaneStack( lanename=self.opts['id'], yid=salt.utils.gen_jid(), dirpath=self.opts['cachedir'], sockdirpath=self.opts['sock_dir']) self.stack.Pk = raeting.packKinds.pack self.router_yard = yarding.RemoteYard( yid=0, prefix=self.opts['id'], dirpath=self.opts['sock_dir']) self.stack.addRemote(self.router_yard) src = (self.opts['id'], self.stack.local.name, None) dst = ('master', None, 'remote_cmd') self.route = {'src': src, 'dst': dst} 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): ''' Send a message load and wait for a relative reply ''' msg = {'route': self.route, 'load': load} self.stack.transmit(msg, self.stack.uids['yard0']) while True: time.sleep(0.01) self.stack.serviceAll() if self.stack.rxMsgs: for msg in self.stack.rxMsgs: return msg.get('return', {})
def _setup_stack(self, ryn='manor'): kind = self.opts.get('__role', '') # opts optional for master if kind: # not all uses of Raet SaltEvent has opts defined if kind not in kinds.APPL_KINDS: emsg = ("Invalid application kind = '{0}' for RAET SaltEvent.".format(kind)) log.error(emsg + "\n") raise ValueError(emsg) if kind != self.node: emsg = ("Mismatch between node = '{0}' and kind = '{1}' in " "RAET SaltEvent.".format(self.node, kind)) log.error(emsg + '\n') raise ValueError(emsg) if self.node in [kinds.APPL_KIND_NAMES[kinds.applKinds.master], kinds.APPL_KIND_NAMES[kinds.applKinds.syndic]]: # []'master', 'syndic'] lanename = 'master' elif self.node in [kinds.APPL_KIND_NAMES[kinds.applKinds.minion], kinds.APPL_KIND_NAMES[kinds.applKinds.caller]]: # ['minion', 'caller'] role = self.opts.get('id', '') # opts required for minion if not role: emsg = ("Missing role required to setup RAET SaltEvent.") log.error(emsg + "\n") raise ValueError(emsg) if not kind: emsg = "Missing kind required to setup RAET SaltEvent." log.error(emsg + '\n') raise ValueError(emsg) lanename = "{0}_{1}".format(role, kind) else: emsg = ("Unsupported application node kind '{0}' for RAET SaltEvent.".format(self.node)) log.error(emsg + '\n') raise ValueError(emsg) name = 'event' + nacling.uuid(size=18) cachedir = self.opts.get('cachedir', os.path.join(syspaths.CACHE_DIR, self.node)) stack = LaneStack( name=name, lanename=lanename, sockdirpath=self.sock_dir) stack.Pk = raeting.PackKind.pack.value stack.addRemote(RemoteYard(stack=stack, lanename=lanename, name=ryn, dirpath=self.sock_dir)) return stack
def _setup(opts, ryn='manor'): ''' Setup the LaneStack lane_stack and RemoteYard lane_remote_yard global ''' global lane_stack, remote_yard # pylint: disable=W0602 role = opts.get('id') if not role: emsg = ("Missing role required to setup LaneStack.") log.error(emsg + "\n") raise ValueError(emsg) kind = opts.get('__role') # application kind 'master', 'minion', etc if kind not in kinds.APPL_KINDS: emsg = ("Invalid application kind = '{0}' for LaneStack.".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 == [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 LaneStack.".format(kind)) log.error(emsg + '\n') raise ValueError(emsg) name = 'lanestack' + nacling.uuid(size=18) lane_stack = LaneStack(name=name, lanename=lanename, sockdirpath=opts['sock_dir']) lane_stack.Pk = raeting.PackKind.pack.value log.debug("Created new LaneStack and local Yard named {0} at {1}\n" "".format(lane_stack.name, lane_stack.ha)) remote_yard = RemoteYard(stack=lane_stack, name=ryn, lanename=lanename, dirpath=opts['sock_dir']) lane_stack.addRemote(remote_yard) log.debug("Added to LaneStack {0} remote Yard named {1} at {2}\n" "".format(lane_stack.name, remote_yard.name, remote_yard.ha))
def pub(self, tgt, fun, arg=(), expr_form='glob', ret='', jid='', timeout=5, **kwargs): ''' Publish the command! ''' payload_kwargs = self._prep_pub( tgt, fun, arg=arg, expr_form=expr_form, ret=ret, jid=jid, timeout=timeout, **kwargs) yid = salt.utils.gen_jid() stack = LaneStack( yid=yid, lanename='master', sockdirpath=self.opts['sock_dir']) stack.Pk = raeting.packKinds.pack router_yard = RemoteYard( prefix='master', yid=0, dirpath=self.opts['sock_dir']) stack.addRemote(router_yard) route = {'dst': (None, router_yard.name, 'local_cmd'), 'src': (None, stack.local.name, None)} msg = {'route': route, 'load': payload_kwargs} stack.transmit(msg) stack.serviceAll() while True: time.sleep(0.01) stack.serviceAll() for msg in stack.rxMsgs: return msg.get('return', {}).get('ret', {})
def _setup_stack(self): ''' 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 ''' import wingdbstub mid = self.opts['id'] yid = nacling.uuid(size=18) name = 'channel' + yid stack = LaneStack(name=name, lanename=mid, sockdirpath=self.opts['sock_dir']) stack.Pk = raeting.packKinds.pack stack.addRemote(RemoteYard(stack=stack, name='manor', lanename=mid, dirpath=self.opts['sock_dir'])) log.debug("Created Channel Jobber Stack {0}\n".format(stack.name)) return stack
def _setup_jobber_stack(self): ''' Setup and return the LaneStack and Yard used by the jobber to communicate to-from the minion ''' mid = self.opts['id'] yid = nacling.uuid(size=18) name = 'jobber' + yid stack = LaneStack( name=name, lanename=mid, sockdirpath=self.opts['sock_dir']) stack.Pk = raeting.packKinds.pack stack.addRemote(RemoteYard(stack=stack, name='manor', lanename=mid, dirpath=self.opts['sock_dir'])) console.concise("Created Jobber Stack {0}\n".format(stack.name)) return stack
def _setup_jobber_stack(self): ''' Setup and return the LaneStack and Yard used by the jobber yard to communicate with the minion manor yard ''' role = self.opts.get('id', '') if not role: emsg = ("Missing role required to setup Jobber Lane.") log.error(emsg + "\n") raise ValueError(emsg) kind = self.opts['__role'] if kind not in kinds.APPL_KINDS: emsg = ("Invalid application kind = '{0}' for Jobber lane.".format(kind)) log.error(emsg + "\n") raise ValueError(emsg) if kind == 'minion': lanename = "{0}_{1}".format(role, kind) else: emsg = ("Unsupported application kind = '{0}' for Jobber Lane.".format(kind)) log.error(emsg + '\n') raise ValueError(emsg) sockdirpath = self.opts['sock_dir'] name = 'jobber' + nacling.uuid(size=18) stack = LaneStack( name=name, lanename=lanename, sockdirpath=sockdirpath) stack.Pk = raeting.packKinds.pack # add remote for the manor yard stack.addRemote(RemoteYard(stack=stack, name='manor', lanename=lanename, dirpath=sockdirpath)) console.concise("Created Jobber Stack {0}\n".format(stack.name)) return stack
def _setup_stack(self): ''' 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 ''' kind = self.opts.get('__role', '') # application kind 'master', 'minion', etc if not kind: emsg = ("Missing opts['__role']. required to setup RAETChannel.") log.error(emsg + "\n") raise ValueError(emsg) if kind == 'master': lanename = 'master' elif kind == 'minion': role = self.opts.get('id', '') if not role: emsg = ("Missing opts['id']. required to setup RAETChannel.") log.error(emsg + "\n") raise ValueError(emsg) lanename = role # add kind later else: emsg = ("Unsupported application kind '{0}' for RAETChannel " "Raet.".format(self.node)) log.error(emsg + '\n') raise ValueError(emsg) mid = self.opts.get('id', 'master') uid = nacling.uuid(size=18) name = 'channel' + uid stack = LaneStack(name=name, lanename=lanename, sockdirpath=self.opts['sock_dir']) stack.Pk = raeting.packKinds.pack stack.addRemote(RemoteYard(stack=stack, name='manor', lanename=lanename, dirpath=self.opts['sock_dir'])) log.debug("Created Channel Jobber Stack {0}\n".format(stack.name)) return stack
def action(self): self.presence_req.value = deque() self.availables.value = set() self.alloweds.value = odict() self.aliveds.value = odict() self.reapeds.value = odict() # Create event stack name = "event" + nacling.uuid(size=18) lanename = self.lane_stack.value.local.lanename sock_dir = self.lane_stack.value.local.dirpath ryn = "manor" console.terse("Create stack: name = {0}, lanename = {1}, sock_dir = {2}\n".format(name, lanename, sock_dir)) stack = LaneStack(name=name, lanename=lanename, sockdirpath=sock_dir) stack.addRemote(RemoteYard(stack=stack, lanename=lanename, name=ryn, dirpath=sock_dir)) self.event_stack.value = stack route = {"dst": (None, ryn, "presence_req"), "src": (None, stack.local.name, None)} msg = {"route": route} stack.transmit(msg, stack.nameRemotes[ryn].uid) serviceLanes([stack, self.lane_stack.value])
def _setup_caller_stack(self, opts): ''' 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 = opts.get('id') if not role: emsg = ("Missing role required to setup RAETChannel.") log.error(emsg + "\n") raise ValueError(emsg) kind = opts.get('__role') # application kind 'master', 'minion', etc if kind not in kinds.APPL_KINDS: emsg = ("Invalid application kind = '{0}' for RAETChannel.".format(kind)) log.error(emsg + "\n") raise ValueError(emsg) if 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 RAETChannel.".format(kind)) log.error(emsg + '\n') raise ValueError(emsg) sockdirpath = opts['sock_dir'] stackname = 'caller' + nacling.uuid(size=18) stack = LaneStack(name=stackname, lanename=lanename, sockdirpath=sockdirpath) stack.Pk = raeting.PackKind.pack.value stack.addRemote(RemoteYard(stack=stack, name='manor', lanename=lanename, dirpath=sockdirpath)) log.debug("Created Caller Jobber Stack {0}\n".format(stack.name)) return stack
def _return_pub(self, msg, ret): ''' Send the return data back via the uxd socket ''' stackname = self.opts['id'] + ret['jid'] dirpath = os.path.join(self.opts['cachedir'], stackname) ret_stack = LaneStack( name=stackname, lanename=self.opts['id'], yid=ret['jid'], sockdirpath=self.opts['sock_dir'], dirpath=dirpath) ret_stack.Pk = raeting.packKinds.pack main_yard = RemoteYard( stack=ret_stack, yid=0, lanename=self.opts['id'], dirpath=self.opts['sock_dir'] ) ret_stack.addRemote(main_yard) route = {'src': (self.opts['id'], ret_stack.local.name, 'jid_ret'), 'dst': (msg['route']['src'][0], None, 'remote_cmd')} ret['cmd'] = '_return' ret['id'] = self.opts['id'] try: oput = self.modules.value[ret['fun']].__outputter__ except (KeyError, AttributeError, TypeError): pass else: if isinstance(oput, str): ret['out'] = oput msg = {'route': route, 'load': ret} ret_stack.transmit(msg, ret_stack.uids.get('yard0')) ret_stack.serviceAll()
def pub(self, tgt, fun, arg=(), tgt_type='glob', ret='', jid='', timeout=5, **kwargs): ''' Publish the command! ''' if 'expr_form' in kwargs: salt.utils.warn_until( 'Fluorine', 'The target type should be passed using the \'tgt_type\' ' 'argument instead of \'expr_form\'. Support for using ' '\'expr_form\' will be removed in Salt Fluorine.' ) tgt_type = kwargs.pop('expr_form') payload_kwargs = self._prep_pub( tgt, fun, arg=arg, tgt_type=tgt_type, ret=ret, jid=jid, timeout=timeout, **kwargs) kind = self.opts['__role'] if kind not in kinds.APPL_KINDS: emsg = ("Invalid application kind = '{0}' for Raet LocalClient.".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' else: emsg = ("Unsupported application kind '{0}' for Raet LocalClient.".format(kind)) log.error(emsg + '\n') raise ValueError(emsg) sockdirpath = self.opts['sock_dir'] name = 'client' + nacling.uuid(size=18) stack = LaneStack( name=name, lanename=lanename, sockdirpath=sockdirpath) stack.Pk = raeting.PackKind.pack.value manor_yard = RemoteYard( stack=stack, lanename=lanename, name='manor', dirpath=sockdirpath) stack.addRemote(manor_yard) route = {'dst': (None, manor_yard.name, 'local_cmd'), 'src': (None, stack.local.name, None)} msg = {'route': route, 'load': payload_kwargs} stack.transmit(msg) stack.serviceAll() while True: time.sleep(0.01) stack.serviceAll() while stack.rxMsgs: msg, sender = stack.rxMsgs.popleft() ret = msg.get('return', {}) if 'ret' in ret: stack.server.close() return ret['ret'] stack.server.close() return ret
class SaltEvent(object): ''' The base class used to manage salt events ''' def __init__(self, node, sock_dir=None, listen=True, opts=None): ''' Set up the stack and remote yard ''' self.node = node # application kind 'master', 'minion', 'syndic', 'call' etc self.sock_dir = sock_dir self.listen = listen if opts is None: opts = {} self.opts = opts self.__prep_stack() def __prep_stack(self): if self.node == 'master': lanename = 'master' if self.opts: kind = self.opts.get('__role', '') # opts optional for master if kind and kind != self.node: emsg = ("Mismatch between node '{0}' and kind '{1}' in setup " "of SaltEvent on Raet.".format(self.node, kind)) log.error(emsg + '\n') raise ValueError(emsg) elif self.node == 'minion': role = self.opts.get('id', '') # opts required for minion if not role: emsg = ("Missing opts['id'] required by SaltEvent on Raet with " "node kind {0}.".format(self.node)) log.error(emsg + '\n') raise ValueError(emsg) kind = self.opts.get('__role', '') if kind != self.node: emsg = ("Mismatch between node '{0}' and kind '{1}' in setup " "of SaltEvent on Raet.".format(self.node, kind)) log.error(emsg + '\n') raise ValueError(emsg) lanename = role # add '_minion' else: emsg = ("Unsupported application node kind '{0}' for SaltEvent " "Raet.".format(self.node)) log.error(emsg + '\n') raise ValueError(emsg) name = 'event' + nacling.uuid(size=18) cachedir = self.opts.get('cachedir', os.path.join(syspaths.CACHE_DIR, self.node)) self.connected = False self.stack = LaneStack( name=name, lanename=lanename, sockdirpath=self.sock_dir) self.stack.Pk = raeting.packKinds.pack self.router_yard = RemoteYard( stack=self.stack, lanename=lanename, name='manor', dirpath=self.sock_dir) self.stack.addRemote(self.router_yard) self.connect_pub() def subscribe(self, tag=None): ''' Included for compat with zeromq events, not required ''' return def unsubscribe(self, tag=None): ''' Included for compat with zeromq events, not required ''' return def connect_pub(self): ''' Establish the publish connection ''' if not self.connected and self.listen: try: route = {'dst': (None, self.router_yard.name, 'event_req'), 'src': (None, self.stack.local.name, None)} msg = {'route': route} self.stack.transmit(msg, self.router_yard.uid) self.stack.serviceAll() self.connected = True except Exception: pass def connect_pull(self, timeout=1000): ''' Included for compat with zeromq events, not required ''' return @classmethod def unpack(cls, raw, serial=None): ''' Included for compat with zeromq events, not required ''' return raw def get_event(self, wait=5, tag='', full=False): ''' Get a single publication. IF no publication available THEN block for up to wait seconds AND either return publication OR None IF no publication available. IF wait is 0 then block forever. ''' self.connect_pub() start = time.time() while True: self.stack.serviceAll() if self.stack.rxMsgs: msg, sender = self.stack.rxMsgs.popleft() if 'tag' not in msg and 'data' not in msg: # Invalid event, how did this get here? continue if not msg['tag'].startswith(tag): # Not what we are looking for, throw it away continue if full: return msg else: return msg['data'] if start + wait < time.time(): return None time.sleep(0.01) def get_event_noblock(self): ''' Get the raw event msg without blocking or any other niceties ''' self.connect_pub() self.stack.serviceAll() if self.stack.rxMsgs: msg, sender = self.stack.rxMsgs.popleft() if 'tag' not in msg and 'data' not in msg: # Invalid event, how did this get here? return None return msg def iter_events(self, tag='', full=False): ''' Creates a generator that continuously listens for events ''' while True: data = self.get_event(tag=tag, full=full) if data is None: continue yield data def fire_event(self, data, tag, timeout=1000): ''' Send a single event into the publisher with paylod dict "data" and event identifier "tag" ''' self.connect_pub() # Timeout is retained for compat with zeromq events if not str(tag): # no empty tags allowed raise ValueError('Empty tag.') if not isinstance(data, MutableMapping): # data must be dict raise ValueError('Dict object expected, not "{0!r}".'.format(data)) route = {'dst': (None, self.router_yard.name, 'event_fire'), 'src': (None, self.stack.local.name, None)} msg = {'route': route, 'tag': tag, 'data': data} self.stack.transmit(msg, self.router_yard.uid) self.stack.serviceAll() def fire_ret_load(self, load): ''' Fire events based on information in the return load ''' if load.get('retcode') and load.get('fun'): # Minion fired a bad retcode, fire an event if load['fun'] in salt.utils.event.SUB_EVENT: try: for tag, data in load.get('return', {}).items(): data['retcode'] = load['retcode'] tags = tag.split('_|-') if data.get('result') is False: self.fire_event( data, '{0}.{1}'.format(tags[0], tags[-1])) # old dup event data['jid'] = load['jid'] data['id'] = load['id'] data['success'] = False data['return'] = 'Error: {0}.{1}'.format(tags[0], tags[-1]) data['fun'] = load['fun'] data['user'] = load['user'] self.fire_event( data, salt.utils.event.tagify([load['jid'], 'sub', load['id'], 'error', load['fun']], 'job')) except Exception: pass def destroy(self): if hasattr(self, 'stack'): self.stack.server.close() def __del__(self): self.destroy()
def pub(self, tgt, fun, arg=(), expr_form='glob', ret='', jid='', timeout=5, **kwargs): ''' Publish the command! ''' payload_kwargs = self._prep_pub(tgt, fun, arg=arg, expr_form=expr_form, ret=ret, jid=jid, timeout=timeout, **kwargs) kind = self.opts['__role'] if kind not in kinds.APPL_KINDS: emsg = ("Invalid application kind = '{0}' for Raet LocalClient.". 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' else: emsg = ("Unsupported application kind '{0}' for Raet LocalClient.". format(kind)) log.error(emsg + '\n') raise ValueError(emsg) sockdirpath = self.opts['sock_dir'] name = 'client' + nacling.uuid(size=18) stack = LaneStack(name=name, lanename=lanename, sockdirpath=sockdirpath) stack.Pk = raeting.packKinds.pack manor_yard = RemoteYard(stack=stack, lanename=lanename, name='manor', dirpath=sockdirpath) stack.addRemote(manor_yard) route = { 'dst': (None, manor_yard.name, 'local_cmd'), 'src': (None, stack.local.name, None) } msg = {'route': route, 'load': payload_kwargs} stack.transmit(msg) stack.serviceAll() while True: time.sleep(0.01) stack.serviceAll() while stack.rxMsgs: msg, sender = stack.rxMsgs.popleft() ret = msg.get('return', {}) if 'ret' in ret: stack.server.close() return ret['ret'] stack.server.close() return ret
class SaltEvent(object): ''' The base class used to manage salt events ''' def __init__(self, node, sock_dir=None, listen=True): ''' Set up the stack and remote yard ''' #import wingdbstub self.node = node self.sock_dir = sock_dir self.listen = listen self.__prep_stack() def __prep_stack(self): self.yid = salt.utils.gen_jid() self.connected = False self.stack = LaneStack( yid=self.yid, lanename=self.node, sockdirpath=self.sock_dir) self.stack.Pk = raeting.packKinds.pack self.router_yard = RemoteYard( prefix=self.node, yid=0, dirpath=self.sock_dir) self.stack.addRemote(self.router_yard) self.connect_pub() def subscribe(self, tag=None): ''' Included for compat with zeromq events, not required ''' return def unsubscribe(self, tag=None): ''' Included for compat with zeromq events, not required ''' return def connect_pub(self): ''' Establish the publish connection ''' if not self.connected and self.listen: try: route = {'dst': (None, self.router_yard.name, 'event_req'), 'src': (None, self.stack.local.name, None)} msg = { 'route': route, 'load': {'yid': self.yid, 'dirpath': self.sock_dir}} self.stack.transmit(msg, self.router_yard.uid) self.stack.serviceAll() self.connected = True except Exception: pass def connect_pull(self, timeout=1000): ''' Included for compat with zeromq events, not required ''' return @classmethod def unpack(cls, raw, serial=None): ''' Included for compat with zeromq events, not required ''' return raw def get_event(self, wait=5, tag='', full=False): ''' Get a single publication. IF no publication available THEN block for up to wait seconds AND either return publication OR None IF no publication available. IF wait is 0 then block forever. ''' self.connect_pub() start = time.time() while True: self.stack.serviceAll() if self.stack.rxMsgs: msg = self.stack.rxMsgs.popleft() event = msg.get('event', {}) if 'tag' not in event and 'data' not in event: # Invalid event, how did this get here? continue if not event['tag'].startswith(tag): # Not what we are looking for, throw it away continue if full: return event else: return event['data'] if start + wait < time.time(): return None time.sleep(0.01) def get_event_noblock(self): ''' Get the raw event without blocking or any other niceties ''' self.connect_pub() self.stack.serviceAll() if self.stack.rxMsgs: event = self.stack.rxMsgs.popleft() if 'tag' not in event and 'data' not in event: # Invalid event, how did this get here? return None return event def iter_events(self, tag='', full=False): ''' Creates a generator that continuously listens for events ''' while True: data = self.get_event(tag=tag, full=full) if data is None: continue yield data def fire_event(self, data, tag, timeout=1000): ''' Send a single event into the publisher with paylod dict "data" and event identifier "tag" ''' self.connect_pub() # Timeout is retained for compat with zeromq events if not str(tag): # no empty tags allowed raise ValueError('Empty tag.') if not isinstance(data, MutableMapping): # data must be dict raise ValueError('Dict object expected, not "{0!r}".'.format(data)) route = {'dst': (None, self.router_yard.name, 'event_fire'), 'src': (None, self.stack.local.name, None)} msg = {'route': route, 'tag': tag, 'data': data} self.stack.transmit(msg) self.stack.serviceAll() def fire_ret_load(self, load): ''' Fire events based on information in the return load ''' if load.get('retcode') and load.get('fun'): # Minion fired a bad retcode, fire an event if load['fun'] in salt.utils.event.SUB_EVENT: try: for tag, data in load.get('return', {}).items(): data['retcode'] = load['retcode'] tags = tag.split('_|-') if data.get('result') is False: self.fire_event( data, '{0}.{1}'.format(tags[0], tags[-1])) # old dup event data['jid'] = load['jid'] data['id'] = load['id'] data['success'] = False data['return'] = 'Error: {0}.{1}'.format(tags[0], tags[-1]) data['fun'] = load['fun'] data['user'] = load['user'] self.fire_event( data, salt.utils.event.tagify([load['jid'], 'sub', load['id'], 'error', load['fun']], 'job')) except Exception: pass
class SaltEvent(object): ''' The base class used to manage salt events ''' def __init__(self, node, sock_dir=None, listen=True, opts=None): ''' Set up the stack and remote yard ''' self.node = node self.sock_dir = sock_dir self.listen = listen if opts is None: opts = {} self.opts = opts self.__prep_stack() def __prep_stack(self): self.yid = salt.utils.gen_jid() name = 'event' + self.yid cachedir = self.opts.get('cachedir', os.path.join(syspaths.CACHE_DIR, self.node)) basedirpath = os.path.abspath( os.path.join(cachedir, 'raet')) self.connected = False self.stack = LaneStack( name=name, yid=self.yid, lanename=self.node, basedirpath=basedirpath, sockdirpath=self.sock_dir) self.stack.Pk = raeting.packKinds.pack self.router_yard = RemoteYard( stack=self.stack, lanename=self.node, yid=0, dirpath=self.sock_dir) self.stack.addRemote(self.router_yard) self.connect_pub() def subscribe(self, tag=None): ''' Included for compat with zeromq events, not required ''' return def unsubscribe(self, tag=None): ''' Included for compat with zeromq events, not required ''' return def connect_pub(self): ''' Establish the publish connection ''' if not self.connected and self.listen: try: route = {'dst': (None, self.router_yard.name, 'event_req'), 'src': (None, self.stack.local.name, None)} msg = { 'route': route, 'load': {'yid': self.yid, 'dirpath': self.sock_dir}} self.stack.transmit(msg, self.router_yard.uid) self.stack.serviceAll() self.connected = True except Exception: pass def connect_pull(self, timeout=1000): ''' Included for compat with zeromq events, not required ''' return @classmethod def unpack(cls, raw, serial=None): ''' Included for compat with zeromq events, not required ''' return raw def get_event(self, wait=5, tag='', full=False): ''' Get a single publication. IF no publication available THEN block for up to wait seconds AND either return publication OR None IF no publication available. IF wait is 0 then block forever. ''' self.connect_pub() start = time.time() while True: self.stack.serviceAll() if self.stack.rxMsgs: msg = self.stack.rxMsgs.popleft() event = msg.get('event', {}) if 'tag' not in event and 'data' not in event: # Invalid event, how did this get here? continue if not event['tag'].startswith(tag): # Not what we are looking for, throw it away continue if full: return event else: return event['data'] if start + wait < time.time(): return None time.sleep(0.01) def get_event_noblock(self): ''' Get the raw event without blocking or any other niceties ''' self.connect_pub() self.stack.serviceAll() if self.stack.rxMsgs: event = self.stack.rxMsgs.popleft() if 'tag' not in event and 'data' not in event: # Invalid event, how did this get here? return None return event def iter_events(self, tag='', full=False): ''' Creates a generator that continuously listens for events ''' while True: data = self.get_event(tag=tag, full=full) if data is None: continue yield data def fire_event(self, data, tag, timeout=1000): ''' Send a single event into the publisher with paylod dict "data" and event identifier "tag" ''' self.connect_pub() # Timeout is retained for compat with zeromq events if not str(tag): # no empty tags allowed raise ValueError('Empty tag.') if not isinstance(data, MutableMapping): # data must be dict raise ValueError('Dict object expected, not "{0!r}".'.format(data)) route = {'dst': (None, self.router_yard.name, 'event_fire'), 'src': (None, self.stack.local.name, None)} msg = {'route': route, 'tag': tag, 'data': data} self.stack.transmit(msg) self.stack.serviceAll() def fire_ret_load(self, load): ''' Fire events based on information in the return load ''' if load.get('retcode') and load.get('fun'): # Minion fired a bad retcode, fire an event if load['fun'] in salt.utils.event.SUB_EVENT: try: for tag, data in load.get('return', {}).items(): data['retcode'] = load['retcode'] tags = tag.split('_|-') if data.get('result') is False: self.fire_event( data, '{0}.{1}'.format(tags[0], tags[-1])) # old dup event data['jid'] = load['jid'] data['id'] = load['id'] data['success'] = False data['return'] = 'Error: {0}.{1}'.format(tags[0], tags[-1]) data['fun'] = load['fun'] data['user'] = load['user'] self.fire_event( data, salt.utils.event.tagify([load['jid'], 'sub', load['id'], 'error', load['fun']], 'job')) except Exception: pass