From 1205a9de226c3b77bdb1440818daf5f1f34cf0c9 Mon Sep 17 00:00:00 2001 From: Vincent White Date: Mon, 21 May 2018 00:30:54 +0000 Subject: [PATCH] Don't allow seeds to replace without using unsafe Patch by Vincent White; reviewed by brandonwilliams and edimitrova for CASSANDRA-14463 --- CHANGES.txt | 1 + .../apache/cassandra/service/StorageService.java | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 738fd3a8b7..08a46c0e35 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.25: + * Don't allow seeds to replace without using unsafe (CASSANDRA-14463) * Calculate time remaining correctly for all compaction types in compactionstats (CASSANDRA-14701) * Receipt of gossip shutdown notification updates TokenMetadata (CASSANDRA-16796) * Count bloom filter misses correctly (CASSANDRA-12922) diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 54ea902c93..ac10374eb2 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -570,6 +570,12 @@ public class StorageService extends NotificationBroadcasterSupport implements IE if (!MessagingService.instance().isListening()) MessagingService.instance().listen(); + if (!shouldBootstrap() && !Boolean.getBoolean("cassandra.allow_unsafe_replace")) + throw new RuntimeException("Replacing a node without bootstrapping risks invalidating consistency " + + "guarantees as the expected data may not be present until repair is run. " + + "To perform this operation, please restart with " + + "-Dcassandra.allow_unsafe_replace=true"); + // make magic happen Map epStates = Gossiper.instance.doShadowRound(); // now that we've gossiped at least once, we should be able to find the node we're replacing @@ -810,9 +816,13 @@ public class StorageService extends NotificationBroadcasterSupport implements IE { if (SystemKeyspace.bootstrapComplete()) throw new RuntimeException("Cannot replace address with a node that is already bootstrapped"); - if (!DatabaseDescriptor.isAutoBootstrap()) - throw new RuntimeException("Trying to replace_address with auto_bootstrap disabled will not work, check your configuration"); bootstrapTokens = prepareReplacementInfo(); + if (!shouldBootstrap()) + { + // Will not do replace procedure, persist the tokens we're taking over locally + // so that they don't get clobbered with auto generated ones in joinTokenRing + SystemKeyspace.updateTokens(bootstrapTokens); + } if (isReplacingSameAddress()) { logger.warn("Writes will not be forwarded to this node during replacement because it has the same address as " +