Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
 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],))
Ejemplo n.º 6
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')
Ejemplo n.º 7
0
 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')
Ejemplo n.º 8
0
    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()
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
    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
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
 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()
Ejemplo n.º 14
0
    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
Ejemplo n.º 16
0
    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()
Ejemplo n.º 17
0
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'])
Ejemplo n.º 18
0
 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)
Ejemplo n.º 19
0
 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)
Ejemplo n.º 20
0
def parse_ismaster_response(doc):
    ismaster_response = IsMaster(doc)
    return ServerDescription(address, ismaster_response)
Ejemplo n.º 21
0
 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')
Ejemplo n.º 23
0
 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')
Ejemplo n.º 24
0
 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)
Ejemplo n.º 27
0
 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')
Ejemplo n.º 28
0
 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))