예제 #1
0
 def requestIdentification(self, conn, node_type, uuid, address, name,
                           id_timestamp, extra):
     app = self.app
     self.checkClusterName(name)
     if address == app.server:
         raise ProtocolError('address conflict')
     primary = app.primary_master.getAddress()
     if primary == address:
         primary = None
     elif not app.primary_master.isIdentified():
         if node_type == NodeTypes.MASTER:
             node = app.nm.createMaster(address=address)
             if id_timestamp:
                 conn.close()
                 raise PrimaryElected(node)
         primary = None
     # For some cases, we rely on the fact that the remote will not retry
     # immediately (see SocketConnector.CONNECT_LIMIT).
     known_master_list = [
         node.getAddress() for node in app.nm.getMasterList()
     ]
     conn.send(
         Packets.NotPrimaryMaster(
             primary and known_master_list.index(primary),
             known_master_list))
     conn.abort()
예제 #2
0
    def requestIdentification(self, conn, node_type, uuid, address, name,
                              id_timestamp, extra):
        app = self.app
        self.checkClusterName(name)
        if address == app.server:
            raise ProtocolError('address conflict')
        node = app.nm.getByUUID(uuid)
        by_addr = address and app.nm.getByAddress(address)
        while 1:
            if by_addr:
                if not by_addr.isIdentified():
                    if node is by_addr:
                        break
                    if not node or uuid < 0:
                        # In case of address conflict for a peer with temporary
                        # ids, we'll generate a new id.
                        node = by_addr
                        break
            elif node:
                if node.isIdentified():
                    if uuid < 0:
                        # The peer wants a temporary id that's already assigned.
                        # Let's give it another one.
                        node = uuid = None
                        break
                else:
                    if node is app._node:
                        node = None
                    else:
                        node.setAddress(address)
                    break
                # Id conflict for a storage node.
            else:
                break
            # cloned/evil/buggy node connecting to us
            raise ProtocolError('already connected')

        new_nid = extra.pop('new_nid', None)
        state = NodeStates.RUNNING
        if node_type == NodeTypes.CLIENT:
            if app.cluster_state == ClusterStates.RUNNING:
                handler = app.client_service_handler
            elif app.cluster_state == ClusterStates.BACKINGUP:
                handler = app.client_ro_service_handler
            else:
                raise NotReadyError
            human_readable_node_type = ' client '
        elif node_type == NodeTypes.STORAGE:
            if app.cluster_state == ClusterStates.STOPPING_BACKUP:
                raise NotReadyError
            manager = app._current_manager
            if manager is None:
                manager = app
            state, handler = manager.identifyStorageNode(uuid is not None
                                                         and node is not None)
            if not address:
                if app.cluster_state == ClusterStates.RECOVERING:
                    raise NotReadyError
                if uuid or not new_nid:
                    raise ProtocolError
                state = NodeStates.DOWN
                # We'll let the storage node close the connection. If we
                # aborted it at the end of the method, BootstrapManager
                # (which is used by storage nodes) could see the closure
                # and try to reconnect to a master.
            human_readable_node_type = ' storage (%s) ' % (state, )
        elif node_type == NodeTypes.MASTER:
            if app.election:
                if id_timestamp and \
                  (id_timestamp, address) < (app.election, app.server):
                    raise PrimaryElected(
                        by_addr or app.nm.createMaster(address=address))
                handler = app.election_handler
            else:
                handler = app.secondary_handler
            human_readable_node_type = ' master '
        elif node_type == NodeTypes.ADMIN:
            handler = app.administration_handler
            human_readable_node_type = 'n admin '
        else:
            raise ProtocolError

        uuid = app.getNewUUID(uuid, address, node_type)
        logging.info('Accept a' + human_readable_node_type + uuid_str(uuid))
        if node is None:
            node = app.nm.createFromNodeType(node_type,
                                             uuid=uuid,
                                             address=address)
        else:
            node.setUUID(uuid)
        node.extra = extra
        node.id_timestamp = monotonic_time()
        node.setState(state)
        app.broadcastNodesInformation([node])
        if new_nid:
            changed_list = []
            for offset in new_nid:
                changed_list.append((offset, uuid, CellStates.OUT_OF_DATE))
                app.pt._setCell(offset, node, CellStates.OUT_OF_DATE)
            app.broadcastPartitionChanges(changed_list)
        conn.setHandler(handler)
        node.setConnection(conn, not node.isIdentified())

        conn.answer(
            Packets.AcceptIdentification(NodeTypes.MASTER, app.uuid, uuid))
        handler._notifyNodeInformation(conn)
        handler.handlerSwitched(conn, True)
예제 #3
0
 def _acceptIdentification(self, node):
     raise PrimaryElected(node)
예제 #4
0
    def requestIdentification(self, conn, node_type, uuid,
                              address, name, id_timestamp):
        app = self.app
        self.checkClusterName(name)
        if address == app.server:
            raise ProtocolError('address conflict')
        node = app.nm.getByUUID(uuid)
        by_addr = address and app.nm.getByAddress(address)
        while 1:
            if by_addr:
                if not by_addr.isIdentified():
                    if node is by_addr:
                        break
                    if not node or uuid < 0:
                        # In case of address conflict for a peer with temporary
                        # ids, we'll generate a new id.
                        node = by_addr
                        break
            elif node:
                if node.isIdentified():
                    if uuid < 0:
                        # The peer wants a temporary id that's already assigned.
                        # Let's give it another one.
                        node = uuid = None
                        break
                else:
                    if node is app._node:
                        node = None
                    else:
                        node.setAddress(address)
                    break
                # Id conflict for a storage node.
            else:
                break
            # cloned/evil/buggy node connecting to us
            raise ProtocolError('already connected')

        state = NodeStates.RUNNING
        if node_type == NodeTypes.CLIENT:
            if app.cluster_state == ClusterStates.RUNNING:
                handler = app.client_service_handler
            elif app.cluster_state == ClusterStates.BACKINGUP:
                handler = app.client_ro_service_handler
            else:
                raise NotReadyError
            human_readable_node_type = ' client '
        elif node_type == NodeTypes.STORAGE:
            if app.cluster_state == ClusterStates.STOPPING_BACKUP:
                raise NotReadyError
            manager = app._current_manager
            if manager is None:
                manager = app
            state, handler = manager.identifyStorageNode(
                uuid is not None and node is not None)
            human_readable_node_type = ' storage (%s) ' % (state, )
        elif node_type == NodeTypes.MASTER:
            if app.election:
                if id_timestamp and \
                  (id_timestamp, address) < (app.election, app.server):
                    raise PrimaryElected(by_addr or
                        app.nm.createMaster(address=address))
                handler = app.election_handler
            else:
                handler = app.secondary_handler
            human_readable_node_type = ' master '
        elif node_type == NodeTypes.ADMIN:
            handler = app.administration_handler
            human_readable_node_type = 'n admin '
        else:
            raise ProtocolError

        uuid = app.getNewUUID(uuid, address, node_type)
        logging.info('Accept a' + human_readable_node_type + uuid_str(uuid))
        if node is None:
            node = app.nm.createFromNodeType(node_type,
                uuid=uuid, address=address)
        else:
            node.setUUID(uuid)
        node.id_timestamp = monotonic_time()
        node.setState(state)
        conn.setHandler(handler)
        node.setConnection(conn, not node.isIdentified())
        app.broadcastNodesInformation([node], node)

        conn.answer(Packets.AcceptIdentification(
            NodeTypes.MASTER,
            app.uuid,
            app.pt.getPartitions(),
            app.pt.getReplicas(),
            uuid))
        handler._notifyNodeInformation(conn)
        handler.connectionCompleted(conn, True)