This is an automated email from the ASF dual-hosted git repository.

sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new 1d7a489  ISSUE #1026: initbookie cmd
1d7a489 is described below

commit 1d7a489afb8fee8754b2da1d45745a47542eeca7
Author: cguttapalem <[email protected]>
AuthorDate: Mon Jan 22 21:32:58 2018 -0800

    ISSUE #1026: initbookie cmd
    
    Descriptions of the changes in this PR:
    
    - adding a new BookieShell command - "initbookie" command to decouple from
    bookieformat. This command initializes bookie, by making sure that the
    journalDirs, ledgerDirs and indexDirs are empty and there is no
    registered Bookie with this BookieId.
    
    Master Issue: #1027
    
    Author: cguttapalem <[email protected]>
    
    Reviewers: Sijie Guo <[email protected]>
    
    This closes #1027 from reddycharan/initbookiecmd, closes #1026
---
 .../org/apache/bookkeeper/bookie/BookieShell.java  | 36 +++++++++++
 .../apache/bookkeeper/client/BookKeeperAdmin.java  | 69 ++++++++++++++++++++++
 .../bookkeeper/discover/RegistrationManager.java   | 11 ++++
 .../bookkeeper/discover/ZKRegistrationManager.java | 16 +++++
 .../bookkeeper/client/BookKeeperAdminTest.java     | 45 ++++++++++++++
 5 files changed, 177 insertions(+)

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 5235110..82ad868 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 @@ public class BookieShell implements Tool {
     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";
@@ -328,6 +329,40 @@ public class BookieShell implements Tool {
     }
 
     /**
+     * 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.
      */
     class RecoverCmd extends MyCommand {
@@ -2526,6 +2561,7 @@ public class BookieShell implements Tool {
 
     {
         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 2c5b9df..85527d6 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.Lists;
 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.ExecutionException;
 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;
@@ -1155,6 +1160,70 @@ public class BookKeeperAdmin implements AutoCloseable {
     }
 
     /**
+     * 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 d4a021b..d0c304b 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
@@ -99,6 +99,17 @@ public interface RegistrationManager extends AutoCloseable {
     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.
      *
      * @param bookieId bookie id
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 37aea09..527af78 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 class ZKRegistrationManager implements 
RegistrationManager {
             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 14551a8..3f3e840 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.assertEquals;
 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.meta.ZkLedgerUnderreplicationManager;
 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 class BookKeeperAdminTest extends 
BookKeeperClusterTestCase {
         }
         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));
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to