sijie closed pull request #1027: ISSUE #1026: initbookie cmd
URL: https://github.com/apache/bookkeeper/pull/1027
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
index 523511079..82ad868c5 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
@@ -139,6 +139,7 @@
static final String LEDGERID_FORMATTER_OPT = "ledgeridformat";
static final String CMD_METAFORMAT = "metaformat";
+ static final String CMD_INITBOOKIE = "initbookie";
static final String CMD_BOOKIEFORMAT = "bookieformat";
static final String CMD_RECOVER = "recover";
static final String CMD_LEDGER = "ledger";
@@ -327,6 +328,40 @@ int runCmd(CommandLine cmdLine) throws Exception {
}
}
+ /**
+ * Initializes bookie, by making sure that the journalDir, ledgerDirs and
+ * indexDirs are empty and there is no registered Bookie with this
BookieId.
+ */
+ class InitBookieCmd extends MyCommand {
+ Options opts = new Options();
+
+ public InitBookieCmd() {
+ super(CMD_INITBOOKIE);
+ }
+
+ @Override
+ Options getOptions() {
+ return opts;
+ }
+
+ @Override
+ String getDescription() {
+ return "Initialize new Bookie";
+ }
+
+ @Override
+ String getUsage() {
+ return CMD_INITBOOKIE;
+ }
+
+ @Override
+ int runCmd(CommandLine cmdLine) throws Exception {
+ ServerConfiguration conf = new ServerConfiguration(bkConf);
+ boolean result = BookKeeperAdmin.initBookie(conf);
+ return (result) ? 0 : 1;
+ }
+ }
+
/**
* Recover command for ledger data recovery for failed bookie.
*/
@@ -2526,6 +2561,7 @@ int runCmd(CommandLine cmdLine) throws Exception {
{
commands.put(CMD_METAFORMAT, new MetaFormatCmd());
+ commands.put(CMD_INITBOOKIE, new InitBookieCmd());
commands.put(CMD_BOOKIEFORMAT, new BookieFormatCmd());
commands.put(CMD_RECOVER, new RecoverCmd());
commands.put(CMD_LEDGER, new LedgerCmd());
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java
index 2c5b9dfd5..85527d674 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperAdmin.java
@@ -26,6 +26,8 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.AbstractFuture;
+
+import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@@ -48,6 +50,9 @@
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
+
+import org.apache.bookkeeper.bookie.Bookie;
+import org.apache.bookkeeper.bookie.BookieException;
import org.apache.bookkeeper.client.AsyncCallback.OpenCallback;
import org.apache.bookkeeper.client.AsyncCallback.RecoverCallback;
import
org.apache.bookkeeper.client.LedgerFragmentReplicator.SingleFragmentCallback;
@@ -1154,6 +1159,70 @@ public static boolean format(ServerConfiguration conf,
}
}
+ /**
+ * Initializes bookie, by making sure that the journalDir, ledgerDirs and
+ * indexDirs are empty and there is no registered Bookie with this
BookieId.
+ *
+ * @param conf
+ * @return
+ * @throws Exception
+ */
+ public static boolean initBookie(ServerConfiguration conf) throws
Exception {
+ /*
+ * make sure that journalDirs, ledgerDirs and indexDirs are empty
+ */
+ File[] journalDirs = conf.getJournalDirs();
+ if (!validateDirectoriesAreEmpty(journalDirs, "JournalDir")) {
+ return false;
+ }
+
+ File[] ledgerDirs = conf.getLedgerDirs();
+ if (!validateDirectoriesAreEmpty(ledgerDirs, "LedgerDir")) {
+ return false;
+ }
+
+ File[] indexDirs = conf.getIndexDirs();
+ if (indexDirs != null) {
+ if (!validateDirectoriesAreEmpty(indexDirs, "IndexDir")) {
+ return false;
+ }
+ }
+
+ try (RegistrationManager rm =
RegistrationManager.instantiateRegistrationManager(conf)) {
+ /*
+ * make sure that there is no bookie registered with the same
+ * bookieid and the cookie for the same bookieid is not existing.
+ */
+ String bookieId = Bookie.getBookieAddress(conf).toString();
+ if (rm.isBookieRegistered(bookieId)) {
+ LOG.error("Bookie with bookieId: {} is still registered, "
+ + "If this node is running bookie process, try
stopping it first.", bookieId);
+ return false;
+ }
+
+ try {
+ rm.readCookie(bookieId);
+ LOG.error("Cookie still exists in the ZK for this bookie: {},
try formatting the bookie", bookieId);
+ return false;
+ } catch (BookieException.CookieNotFoundException nfe) {
+ // it is expected for readCookie to fail with
+ // BookieException.CookieNotFoundException
+ }
+ return true;
+ }
+ }
+
+ private static boolean validateDirectoriesAreEmpty(File[] dirs, String
typeOfDir) {
+ for (File dir : dirs) {
+ File[] dirFiles = dir.listFiles();
+ if ((dirFiles != null) && dirFiles.length != 0) {
+ LOG.error("{}: {} is existing and its not empty, try
formatting the bookie", typeOfDir, dir);
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* This method returns an iterable object for the list of ledger
identifiers of
* the ledgers currently available.
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/RegistrationManager.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/RegistrationManager.java
index d4a021b33..d0c304bc3 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/RegistrationManager.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/RegistrationManager.java
@@ -98,6 +98,17 @@ RegistrationManager initialize(ServerConfiguration conf,
*/
void unregisterBookie(String bookieId, boolean readOnly) throws
BookieException;
+ /**
+ * Checks if Bookie with the given BookieId is registered as readwrite or
+ * readonly bookie.
+ *
+ * @param bookieId bookie id
+ * @return returns true if a bookie with bookieid is currently registered
as
+ * readwrite or readonly bookie.
+ * @throws BookieException
+ */
+ boolean isBookieRegistered(String bookieId) throws BookieException;
+
/**
* Write the cookie data, which will be used for verifying the integrity
of the bookie environment.
*
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/ZKRegistrationManager.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/ZKRegistrationManager.java
index 37aea0950..527af780d 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/ZKRegistrationManager.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/discover/ZKRegistrationManager.java
@@ -513,4 +513,20 @@ public boolean format(ServerConfiguration conf) throws
Exception {
return true;
}
}
+
+ @Override
+ public boolean isBookieRegistered(String bookieId) throws BookieException {
+ String regPath = bookieRegistrationPath + "/" + bookieId;
+ String readonlyRegPath = bookieReadonlyRegistrationPath + "/" +
bookieId;
+ try {
+ return ((null != zk.exists(regPath, false)) || (null !=
zk.exists(readonlyRegPath, false)));
+ } catch (KeeperException e) {
+ log.error("ZK exception while checking registration ephemeral
znodes for BookieId: {}", bookieId, e);
+ throw new MetadataStoreException(e);
+ } catch (InterruptedException e) {
+ log.error("InterruptedException while checking registration
ephemeral znodes for BookieId: {}", bookieId,
+ e);
+ throw new MetadataStoreException(e);
+ }
+ }
}
diff --git
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookKeeperAdminTest.java
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookKeeperAdminTest.java
index 14551a83b..3f3e8402c 100644
---
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookKeeperAdminTest.java
+++
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookKeeperAdminTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.File;
import java.util.Iterator;
import org.apache.bookkeeper.bookie.Bookie;
@@ -34,6 +35,9 @@
import
org.apache.bookkeeper.replication.ReplicationException.UnavailableException;
import org.apache.bookkeeper.test.BookKeeperClusterTestCase;
import org.apache.bookkeeper.test.annotations.FlakyTest;
+import org.apache.bookkeeper.util.BookKeeperConstants;
+import org.apache.commons.io.FileUtils;
+import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -230,4 +234,45 @@ public void
testDecommissionForLedgersWithMultipleSegmentsAndNotWriteClosed() th
}
bkAdmin.close();
}
+
+ @Test(timeout = 6000000)
+ public void testBookieInit() throws Exception {
+ int bookieindex = 0;
+ ServerConfiguration confOfExistingBookie = bsConfs.get(bookieindex);
+ Assert.assertFalse("initBookie shouldn't have succeeded, since bookie
is still running with that configuration",
+ BookKeeperAdmin.initBookie(confOfExistingBookie));
+ killBookie(bookieindex);
+ Assert.assertFalse("initBookie shouldn't have succeeded, since
previous bookie is not formatted yet",
+ BookKeeperAdmin.initBookie(confOfExistingBookie));
+
+ File[] journalDirs = confOfExistingBookie.getJournalDirs();
+ for (File journalDir : journalDirs) {
+ FileUtils.deleteDirectory(journalDir);
+ }
+ Assert.assertFalse("initBookie shouldn't have succeeded, since
previous bookie is not formatted yet completely",
+ BookKeeperAdmin.initBookie(confOfExistingBookie));
+
+ File[] ledgerDirs = confOfExistingBookie.getLedgerDirs();
+ for (File ledgerDir : ledgerDirs) {
+ FileUtils.deleteDirectory(ledgerDir);
+ }
+ Assert.assertFalse("initBookie shouldn't have succeeded, since
previous bookie is not formatted yet completely",
+ BookKeeperAdmin.initBookie(confOfExistingBookie));
+
+ File[] indexDirs = confOfExistingBookie.getIndexDirs();
+ if (indexDirs != null) {
+ for (File indexDir : indexDirs) {
+ FileUtils.deleteDirectory(indexDir);
+ }
+ }
+ Assert.assertFalse("initBookie shouldn't have succeeded, since cookie
in ZK is not deleted yet",
+ BookKeeperAdmin.initBookie(confOfExistingBookie));
+ String bookieId =
Bookie.getBookieAddress(confOfExistingBookie).toString();
+ String bookieCookiePath = confOfExistingBookie.getZkLedgersRootPath()
+ "/" + BookKeeperConstants.COOKIE_NODE
+ + "/" + bookieId;
+ zkc.delete(bookieCookiePath, -1);
+
+ Assert.assertTrue("initBookie shouldn't succeeded",
+ BookKeeperAdmin.initBookie(confOfExistingBookie));
+ }
}
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services