def ismaster(self, metadata, cluster_time): cmd = SON([('ismaster', 1)]) if not self.performed_handshake: cmd['client'] = metadata if self.compression_settings: cmd['compression'] = self.compression_settings.compressors if self.max_wire_version >= 6 and cluster_time is not None: cmd['$clusterTime'] = cluster_time ismaster = IsMaster(self.command('admin', cmd, publish_events=False)) self.is_writable = ismaster.is_writable self.max_wire_version = ismaster.max_wire_version self.max_bson_size = ismaster.max_bson_size self.max_message_size = ismaster.max_message_size self.max_write_batch_size = ismaster.max_write_batch_size self.supports_sessions = ( ismaster.logical_session_timeout_minutes is not None) self.is_mongos = ismaster.server_type == SERVER_TYPE.Mongos if not self.performed_handshake and self.compression_settings: ctx = self.compression_settings.get_compression_context( ismaster.compressors) self.compression_context = ctx self.performed_handshake = True self.op_msg_enabled = ismaster.max_wire_version >= 6 return ismaster
def connect(self): """Connect to Mongo and return a new SocketInfo. Can raise ConnectionFailure or CertificateError. Note that the pool does not keep a reference to the socket -- you must call return_socket() when you're done with it. """ sock = None try: sock = _configured_socket(self.address, self.opts) if self.handshake: cmd = SON([ ('ismaster', 1), ('client', self.opts.metadata) ]) ismaster = IsMaster( command(sock, 'admin', cmd, False, False, ReadPreference.PRIMARY, DEFAULT_CODEC_OPTIONS, None)) else: ismaster = None return SocketInfo(sock, self, ismaster, self.address) except socket.error as error: if sock is not None: sock.close() _raise_connection_failure(self.address, error)
def __init__( self, address, ismaster=None, round_trip_time=None, error=None): self._address = address if not ismaster: ismaster = IsMaster({}) self._server_type = ismaster.server_type self._all_hosts = ismaster.all_hosts self._tags = ismaster.tags self._replica_set_name = ismaster.replica_set_name self._primary = ismaster.primary self._max_bson_size = ismaster.max_bson_size self._max_message_size = ismaster.max_message_size self._max_write_batch_size = ismaster.max_write_batch_size self._min_wire_version = ismaster.min_wire_version self._max_wire_version = ismaster.max_wire_version self._set_version = ismaster.set_version self._election_id = ismaster.election_id self._is_writable = ismaster.is_writable self._is_readable = ismaster.is_readable self._round_trip_time = round_trip_time self._me = ismaster.me self._error = error
def __init__(self, address, ismaster=None, round_trip_time=None, error=None): self._address = address if not ismaster: ismaster = IsMaster({}) self._server_type = ismaster.server_type self._all_hosts = ismaster.all_hosts self._tags = ismaster.tags self._replica_set_name = ismaster.replica_set_name self._primary = ismaster.primary self._max_bson_size = ismaster.max_bson_size self._max_message_size = ismaster.max_message_size self._max_write_batch_size = ismaster.max_write_batch_size self._min_wire_version = ismaster.min_wire_version self._max_wire_version = ismaster.max_wire_version self._set_version = ismaster.set_version self._election_id = ismaster.election_id self._is_writable = ismaster.is_writable self._is_readable = ismaster.is_readable self._round_trip_time = round_trip_time self._me = ismaster.me self._last_update_time = _time() self._error = error if ismaster.last_write_date: # Convert from datetime to seconds. delta = ismaster.last_write_date - EPOCH_NAIVE self._last_write_date = _total_seconds(delta) else: self._last_write_date = None
def _check_with_socket(self, *args, **kwargs): ismaster_count[0] += 1 if ismaster_count[0] in (1, 3): return IsMaster({'ok': 1, 'maxWireVersion': 6}), 0 else: raise AutoReconnect( 'mock monitor error #%s' % (ismaster_count[0],))
def _check_with_socket(self, *args, **kwargs): if available: return (IsMaster({ 'ok': 1, 'maxWireVersion': 6 }), round_trip_time) else: raise AutoReconnect('mock monitor error')
def _check_with_socket(self, sock_info, metadata=None): if available: return (IsMaster({ 'ok': 1, 'maxWireVersion': 6 }), round_trip_time) else: raise AutoReconnect('mock monitor error')
async def is_master(self, ignore_connected: bool = False) -> IsMaster: is_master = IsMaster(await self.command( 'admin', SON([('ismaster', 1)]), ReadPreference.PRIMARY, DEFAULT_CODEC_OPTIONS, ignore_connected=ignore_connected, )) return is_master
def _run_scenario(self): class NoopMonitor(Monitor): """Override the _run method to do nothing.""" def _run(self): time.sleep(0.05) m = single_client(h=scenario_def['uri'], p=27017, event_listeners=[self.all_listener], _monitor_class=NoopMonitor) topology = m._get_topology() try: for phase in scenario_def['phases']: for (source, response) in phase['responses']: source_address = clean_node(source) topology.on_change( ServerDescription(address=source_address, ismaster=IsMaster(response), round_trip_time=0)) expected_results = phase['outcome']['events'] expected_len = len(expected_results) wait_until( lambda: len(self.all_listener.results) >= expected_len, "publish all events", timeout=15) # Wait some time to catch possible lagging extra events. time.sleep(0.5) i = 0 while i < expected_len: result = self.all_listener.results[i] if len( self.all_listener.results) > i else None # The order of ServerOpening/ClosedEvents doesn't matter if isinstance(result, (monitoring.ServerOpeningEvent, monitoring.ServerClosedEvent)): i, passed, message = compare_multiple_events( i, expected_results, self.all_listener.results) self.assertTrue(passed, message) else: self.assertTrue( *compare_events(expected_results[i], result)) i += 1 # Assert no extra events. extra_events = self.all_listener.results[expected_len:] if extra_events: self.fail('Extra events %r' % (extra_events, )) self.all_listener.reset() finally: m.close()
def make_server_description(server, hosts): """Make a ServerDescription from server info in a JSON test.""" server_type = server['type'] if server_type == "Unknown": return ServerDescription(clean_node(server['address']), IsMaster({})) ismaster_response = {'ok': True, 'hosts': hosts} if server_type != "Standalone" and server_type != "Mongos": ismaster_response['setName'] = "rs" if server_type == "RSPrimary": ismaster_response['ismaster'] = True elif server_type == "RSSecondary": ismaster_response['secondary'] = True elif server_type == "Mongos": ismaster_response['msg'] = 'isdbgrid' ismaster_response['lastWrite'] = { 'lastWriteDate': make_last_write_date(server) } for field in 'maxWireVersion', 'tags', 'idleWritePeriodMillis': if field in server: ismaster_response[field] = server[field] ismaster_response.setdefault('maxWireVersion', 6) # Sets _last_update_time to now. sd = ServerDescription(clean_node(server['address']), IsMaster(ismaster_response), round_trip_time=server['avg_rtt_ms'] / 1000.0) if 'lastUpdateTime' in server: sd._last_update_time = server['lastUpdateTime'] / 1000.0 # ms to sec. return sd
def _check_with_socket(self, sock_info): """Return (IsMaster, round_trip_time). Can raise ConnectionFailure or OperationFailure. """ start = _time() request_id, msg, max_doc_size = message.query(0, 'admin.$cmd', 0, -1, {'ismaster': 1}, None, DEFAULT_CODEC_OPTIONS) # TODO: use sock_info.command() sock_info.send_message(msg, max_doc_size) raw_response = sock_info.receive_message(1, request_id) result = helpers._unpack_response(raw_response) return IsMaster(result['data'][0]), _time() - start
def _check_with_socket(self, sock_info, metadata=None): """Return (IsMaster, round_trip_time). Can raise ConnectionFailure or OperationFailure. """ cmd = SON([('ismaster', 1)]) if metadata is not None: cmd['client'] = metadata start = _time() request_id, msg, max_doc_size = message.query( 0, 'admin.$cmd', 0, -1, cmd, None, DEFAULT_CODEC_OPTIONS) # TODO: use sock_info.command() sock_info.send_message(msg, max_doc_size) reply = sock_info.receive_message(request_id) return IsMaster(reply.command_response()), _time() - start
def _run(self): try: if self._server_description.address != ('a', 27017): # Because PyMongo doesn't keep information about # the order of addresses, we might accidentally # start a MockMonitor on the wrong server first, # so we need to only mock responses for the server # the test's response is supposed to come from. return response = next(responses)[1] isMaster = IsMaster(response) self._server_description = ServerDescription( address=self._server_description.address, ismaster=isMaster) self._topology.on_change(self._server_description) except (ReferenceError, StopIteration): # Topology was garbage-collected. self.close()
def _check_with_socket(self, conn): """Return (Hello, round_trip_time). Can raise ConnectionFailure or OperationFailure. """ cluster_time = self._topology.max_cluster_time() start = _time() if conn.more_to_come: # Read the next streaming hello (MongoDB 4.4+). response = IsMaster(conn._next_reply(), awaitable=True) elif (conn.performed_handshake and self._server_description.topology_version): # Initiate streaming hello (MongoDB 4.4+). response = conn._hello(cluster_time, self._server_description.topology_version, self._settings.heartbeat_frequency, None) else: # New connection handshake or polling hello (MongoDB <4.4). response = conn._hello(cluster_time, None, None, None) return response, _time() - start
def __init__( self, address, ismaster=None, round_trip_time=None, error=None): self._address = address if not ismaster: ismaster = IsMaster({}) self._server_type = ismaster.server_type self._all_hosts = ismaster.all_hosts self._tags = ismaster.tags self._replica_set_name = ismaster.replica_set_name self._primary = ismaster.primary self._max_bson_size = ismaster.max_bson_size self._max_message_size = ismaster.max_message_size self._max_write_batch_size = ismaster.max_write_batch_size self._min_wire_version = ismaster.min_wire_version self._max_wire_version = ismaster.max_wire_version self._set_version = ismaster.set_version self._election_id = ismaster.election_id self._cluster_time = ismaster.cluster_time self._is_writable = ismaster.is_writable self._is_readable = ismaster.is_readable self._ls_timeout_minutes = ismaster.logical_session_timeout_minutes self._round_trip_time = round_trip_time self._me = ismaster.me self._last_update_time = _time() self._error = error self._topology_version = ismaster.topology_version if error: if hasattr(error, 'details') and isinstance(error.details, dict): self._topology_version = error.details.get('topologyVersion') if ismaster.last_write_date: # Convert from datetime to seconds. delta = ismaster.last_write_date - EPOCH_NAIVE self._last_write_date = delta.total_seconds() else: self._last_write_date = None
async def connect(self) -> None: if self.host.startswith('/'): self.reader, self.writer = await asyncio.open_unix_connection( path=self.host, loop=self.loop) else: self.reader, self.writer = await asyncio.open_connection( host=self.host, port=self.port, loop=self.loop) sock = self.writer.transport.get_extra_info('socket') sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, int(self.options.pool_options.socket_keepalive)) if self.host.startswith('/'): endpoint = self.host else: endpoint = '{}:{}'.format(self.host, self.port) logger.debug('Established connection to {}'.format(endpoint)) self.read_loop_task = asyncio.ensure_future(self.read_loop(), loop=self.loop) ismaster = IsMaster(await self.command('admin', SON([('ismaster', 1)]), ReadPreference.PRIMARY, DEFAULT_CODEC_OPTIONS)) self.is_mongos = ismaster.server_type == SERVER_TYPE.Mongos self.max_wire_version = ismaster.max_wire_version if ismaster.max_bson_size: self.max_bson_size = ismaster.max_bson_size if ismaster.max_message_size: self.max_message_size = ismaster.max_message_size if ismaster.max_write_batch_size: self.max_write_batch_size = ismaster.max_write_batch_size self.is_writable = ismaster.is_writable self.slave_ok = not self.is_mongos and self.options.read_preference != ReadPreference.PRIMARY if self.options.credentials: await self._authenticate() # Notify waiters that connection has been established self.__connected.set()
def make_server_description(server, hosts): """Make ServerDescription from server info from JSON file.""" ismaster_response = {} ismaster_response['tags'] = server['tags'] ismaster_response['ok'] = True ismaster_response['hosts'] = hosts server_type = server['type'] if server_type != "Standalone" and server_type != "Mongos": ismaster_response['setName'] = True if server_type == "RSPrimary": ismaster_response['ismaster'] = True elif server_type == "RSSecondary": ismaster_response['secondary'] = True elif server_type == "Mongos": ismaster_response['msg'] = 'isdbgrid' return ServerDescription(clean_node(server['address']), IsMaster(ismaster_response), round_trip_time=server['avg_rtt_ms'])
def _check_once(self, metadata=None, cluster_time=None): address = self._server_description.address response, rtt = self.client.mock_is_master('%s:%d' % address) return ServerDescription(address, IsMaster(response), rtt)
def _check_once(self): client = self.client address = self._server_description.address response, rtt = client.mock_is_master('%s:%d' % address) return ServerDescription(address, IsMaster(response), rtt)
def parse_ismaster_response(doc): ismaster_response = IsMaster(doc) return ServerDescription(address, ismaster_response)
def _check_with_socket(self, *args, **kwargs): if isinstance(responses[1], Exception): raise responses[1] return IsMaster(responses[1]), 99
def _check_with_socket(self, sock_info, metadata=None): ismaster_count[0] += 1 if ismaster_count[0] == 1: return IsMaster({'ok': 1}), 0 else: raise AutoReconnect('mock monitor error')
def _check_with_socket(self, sock_info): ismaster_count[0] += 1 if ismaster_count[0] in (1, 3): return IsMaster({'ok': 1}), 0 else: raise AutoReconnect('mock monitor error')
def _check_with_socket(self, sock_info): if available: return IsMaster({'ok': 1}), round_trip_time else: raise AutoReconnect('mock monitor error')
def _check_with_socket(self, sock_info, metadata=None): if isinstance(responses[1], Exception): raise responses[1] return IsMaster(responses[1]), 99
def got_ismaster(topology, server_address, ismaster_response): server_description = ServerDescription(server_address, IsMaster(ismaster_response), 0) topology.on_change(server_description)
def _check_with_socket(self, sock_info, metadata=None): ismaster_count[0] += 1 if ismaster_count[0] in (1, 3): return IsMaster({'ok': 1, 'maxWireVersion': 6}), 0 else: raise AutoReconnect('mock monitor error')
def test_repr(self): ismaster = IsMaster({'ok': 1}) sd = ServerDescription(('localhost', 27017), ismaster) server = Server(sd, pool=object(), monitor=object()) self.assertTrue('Standalone' in str(server))