def __init__(self, opts, addr, linger=0, io_loop=None): ''' Create an asynchronous message client :param dict opts: The salt opts dictionary :param str addr: The interface IP address to bind to :param int linger: The number of seconds to linger on a ZMQ socket. See http://api.zeromq.org/2-1:zmq-setsockopt [ZMQ_LINGER] :param IOLoop io_loop: A Tornado IOLoop event scheduler [tornado.ioloop.IOLoop] ''' self.opts = opts self.addr = addr self.linger = linger if io_loop is None: install_zmq() ZMQDefaultLoop.current() else: self.io_loop = io_loop self.serial = salt.payload.Serial(self.opts) self.context = zmq.Context() # wire up sockets self._init_socket() self.send_queue = [] # mapping of message -> future self.send_future_map = {} self.send_timeout_map = {} # message -> timeout
def __new__(cls, opts, **kwargs): ''' Only create one instance of channel per __key() ''' # do we have any mapping for this io_loop io_loop = kwargs.get('io_loop') if io_loop is None: install_zmq() io_loop = ZMQDefaultLoop.current() if io_loop not in cls.instance_map: cls.instance_map[io_loop] = weakref.WeakValueDictionary() loop_instance_map = cls.instance_map[io_loop] key = cls.__key(opts, **kwargs) obj = loop_instance_map.get(key) if obj is None: log.debug('Initializing new AsyncZeroMQReqChannel for %s', key) # we need to make a local variable for this, as we are going to store # it in a WeakValueDictionary-- which will remove the item if no one # references it-- this forces a reference while we return to the caller obj = object.__new__(cls) obj.__singleton_init__(opts, **kwargs) loop_instance_map[key] = obj log.trace('Inserted key into loop_instance_map id %s for key %s and process %s', id(loop_instance_map), key, os.getpid()) else: log.debug('Re-using AsyncZeroMQReqChannel for %s', key) return obj
def __singleton_init__(self, opts, **kwargs): self.opts = dict(opts) self.ttype = 'zeromq' # crypt defaults to 'aes' self.crypt = kwargs.get('crypt', 'aes') if 'master_uri' in kwargs: self.opts['master_uri'] = kwargs['master_uri'] self._io_loop = kwargs.get('io_loop') if self._io_loop is None: install_zmq() self._io_loop = ZMQDefaultLoop.current() if self.crypt != 'clear': # we don't need to worry about auth as a kwarg, since its a singleton self.auth = salt.crypt.AsyncAuth(self.opts, io_loop=self._io_loop) log.debug( 'Connecting the Minion to the Master URI (for the return server): %s', self.master_uri) self.message_client = AsyncReqMessageClientPool( self.opts, args=( self.opts, self.master_uri, ), kwargs={'io_loop': self._io_loop})
def __init__(self, opts, **kwargs): self.opts = opts self.ttype = 'zeromq' self.io_loop = kwargs.get('io_loop') if self.io_loop is None: install_zmq() self.io_loop = ZMQDefaultLoop.current() self.hexid = hashlib.sha1(salt.utils.stringutils.to_bytes(self.opts['id'])).hexdigest() self.auth = salt.crypt.AsyncAuth(self.opts, io_loop=self.io_loop) self.serial = salt.payload.Serial(self.opts) self.context = zmq.Context() self._socket = self.context.socket(zmq.SUB) if self.opts['zmq_filtering']: # TODO: constants file for "broadcast" self._socket.setsockopt(zmq.SUBSCRIBE, b'broadcast') if self.opts.get('__role') == 'syndic': self._socket.setsockopt(zmq.SUBSCRIBE, b'syndic') else: self._socket.setsockopt( zmq.SUBSCRIBE, salt.utils.stringutils.to_bytes(self.hexid) ) else: self._socket.setsockopt(zmq.SUBSCRIBE, b'') self._socket.setsockopt(zmq.IDENTITY, salt.utils.stringutils.to_bytes(self.opts['id'])) # TODO: cleanup all the socket opts stuff if hasattr(zmq, 'TCP_KEEPALIVE'): self._socket.setsockopt( zmq.TCP_KEEPALIVE, self.opts['tcp_keepalive'] ) self._socket.setsockopt( zmq.TCP_KEEPALIVE_IDLE, self.opts['tcp_keepalive_idle'] ) self._socket.setsockopt( zmq.TCP_KEEPALIVE_CNT, self.opts['tcp_keepalive_cnt'] ) self._socket.setsockopt( zmq.TCP_KEEPALIVE_INTVL, self.opts['tcp_keepalive_intvl'] ) recon_delay = self.opts['recon_default'] if self.opts['recon_randomize']: recon_delay = randint(self.opts['recon_default'], self.opts['recon_default'] + self.opts['recon_max']) log.debug( "Generated random reconnect delay between '%sms' and '%sms' (%s)", self.opts['recon_default'], self.opts['recon_default'] + self.opts['recon_max'], recon_delay ) log.debug("Setting zmq_reconnect_ivl to '%sms'", recon_delay) self._socket.setsockopt(zmq.RECONNECT_IVL, recon_delay) if hasattr(zmq, 'RECONNECT_IVL_MAX'): log.debug( "Setting zmq_reconnect_ivl_max to '%sms'", self.opts['recon_default'] + self.opts['recon_max'] ) self._socket.setsockopt( zmq.RECONNECT_IVL_MAX, self.opts['recon_max'] ) if (self.opts['ipv6'] is True or ':' in self.opts['master_ip']) and hasattr(zmq, 'IPV4ONLY'): # IPv6 sockets work for both IPv6 and IPv4 addresses self._socket.setsockopt(zmq.IPV4ONLY, 0) if HAS_ZMQ_MONITOR and self.opts['zmq_monitor']: self._monitor = ZeroMQSocketMonitor(self._socket) self._monitor.start_io_loop(self.io_loop)