Beispiel #1
0
    def requestIdentification(self, conn, node_type, uuid, address, name):
        self.checkClusterName(name)
        app = self.app
        node = app.nm.getByUUID(uuid)
        if node:
            assert node_type is not NodeTypes.MASTER or node.getAddress() in (
                address, None), (node, address)
            if node.isBroken():
                raise BrokenNodeDisallowedError
        else:
            node = app.nm.getByAddress(address)
        peer_uuid = self._setupNode(conn, node_type, uuid, address, node)
        if app.primary:
            primary_address = app.server
        elif app.primary_master_node is not None:
            primary_address = app.primary_master_node.getAddress()
        else:
            primary_address = None

        known_master_list = [(app.server, app.uuid)]
        for n in app.nm.getMasterList():
            if n.isBroken():
                continue
            known_master_list.append((n.getAddress(), n.getUUID()))
        conn.answer(
            Packets.AcceptIdentification(NodeTypes.MASTER, app.uuid,
                                         app.pt.getPartitions(),
                                         app.pt.getReplicas(), peer_uuid,
                                         primary_address, known_master_list), )
Beispiel #2
0
 def requestIdentification(self, conn, node_type, uuid, address, name, *_):
     if node_type != NodeTypes.ADMIN:
         raise ProtocolError("reject non-admin node")
     app = self.app
     try:
         backup = app.backup_dict[name]
     except KeyError:
         raise ProtocolError("unknown backup cluster %r" % name)
     if backup.conn is not None:
         raise ProtocolError("already connected")
     backup.conn = conn
     conn.setHandler(app.backup_handler)
     conn.answer(Packets.AcceptIdentification(NodeTypes.ADMIN, None, None))
Beispiel #3
0
 def requestIdentification(self, conn, node_type, uuid, address, name):
     self.checkClusterName(name)
     # reject any incoming connections if not ready
     if not self.app.ready:
         raise NotReadyError
     app = self.app
     if uuid is None:
         if node_type != NodeTypes.STORAGE:
             raise ProtocolError('reject anonymous non-storage node')
         handler = StorageOperationHandler(self.app)
         conn.setHandler(handler)
     else:
         if uuid == app.uuid:
             raise ProtocolError("uuid conflict or loopback connection")
         node = app.nm.getByUUID(uuid)
         # If this node is broken, reject it.
         if node is not None and node.isBroken():
             raise BrokenNodeDisallowedError
         # choose the handler according to the node type
         if node_type == NodeTypes.CLIENT:
             handler = ClientOperationHandler
             if node is None:
                 node = app.nm.createClient(uuid=uuid)
             elif node.isConnected():
                 # This can happen if we haven't processed yet a notification
                 # from the master, telling us the existing node is not
                 # running anymore. If we accept the new client, we won't
                 # know what to do with this late notification.
                 raise NotReadyError('uuid conflict: retry later')
             node.setRunning()
         elif node_type == NodeTypes.STORAGE:
             if node is None:
                 logging.error('reject an unknown storage node %s',
                               uuid_str(uuid))
                 raise NotReadyError
             handler = StorageOperationHandler
         else:
             raise ProtocolError('reject non-client-or-storage node')
         # apply the handler and set up the connection
         handler = handler(self.app)
         conn.setHandler(handler)
         node.setConnection(conn, app.uuid < uuid)
     # accept the identification and trigger an event
     conn.answer(
         Packets.AcceptIdentification(NodeTypes.STORAGE, uuid and app.uuid,
                                      app.pt.getPartitions(),
                                      app.pt.getReplicas(), uuid,
                                      app.master_node.getAddress(), ()))
     handler.connectionCompleted(conn)
Beispiel #4
0
 def requestIdentification(self, conn, node_type, uuid, address, name,
                           id_timestamp):
     self.checkClusterName(name)
     app = self.app
     # reject any incoming connections if not ready
     if not app.operational:
         raise NotReadyError
     if uuid is None:
         if node_type != NodeTypes.STORAGE:
             raise ProtocolError('reject anonymous non-storage node')
         handler = StorageOperationHandler(self.app)
         conn.setHandler(handler)
     else:
         if uuid == app.uuid:
             raise ProtocolError("uuid conflict or loopback connection")
         node = app.nm.getByUUID(uuid, id_timestamp)
         # choose the handler according to the node type
         if node_type == NodeTypes.CLIENT:
             if app.dm.getBackupTID():
                 handler = ClientReadOnlyOperationHandler
             else:
                 handler = ClientOperationHandler
             assert not node.isConnected(), node
             assert node.isRunning(), node
         elif node_type == NodeTypes.STORAGE:
             handler = StorageOperationHandler
         else:
             raise ProtocolError('reject non-client-or-storage node')
         # apply the handler and set up the connection
         handler = handler(self.app)
         conn.setHandler(handler)
         node.setConnection(conn, app.uuid < uuid)
     # accept the identification and trigger an event
     conn.answer(
         Packets.AcceptIdentification(NodeTypes.STORAGE, uuid and app.uuid,
                                      app.pt.getPartitions(),
                                      app.pt.getReplicas(), uuid))
     handler.connectionCompleted(conn)
Beispiel #5
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)
Beispiel #6
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)