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 _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 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 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])
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 ''' yid = salt.utils.gen_jid() stackname = self.opts['id'] + yid dirpath = os.path.join(self.opts['cachedir'], stackname) self.stack = LaneStack(name=stackname, lanename=self.opts['id'], yid=yid, dirpath=dirpath, sockdirpath=self.opts['sock_dir']) self.stack.Pk = raeting.packKinds.pack self.router_yard = yarding.RemoteYard(stack=self.stack, yid=0, lanename=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 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) 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
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) uid = nacling.uuid(size=18) stack = LaneStack( name=('client' + uid), uid=uid, lanename='master', sockdirpath=self.opts['sock_dir']) stack.Pk = raeting.packKinds.pack router_yard = RemoteYard( stack=stack, lanename='master', uid=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 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() basedirpath = os.path.join(self.opts['cachedir'], 'raet') stack = LaneStack(name=('client' + yid), yid=yid, lanename='master', basedirpath=basedirpath, sockdirpath=self.opts['sock_dir']) stack.Pk = raeting.packKinds.pack router_yard = RemoteYard(stack=stack, lanename='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: ret = msg.get('return', {}) if 'ret' in ret: return ret['ret'] 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 = 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 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 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 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
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