Browse Source

HDFS-13478. RBF: Disabled Nameservice store API. Contributed by Inigo Goiri.

(cherry picked from commit b6dae26f4490bbd03360b8df19ef00cf843430f3)
Yiqun Lin 7 years ago
parent
commit
3f72d077ff
29 changed files with 1520 additions and 12 deletions
  1. 67 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/protocolPB/RouterAdminProtocolServerSideTranslatorPB.java
  2. 63 1
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/protocolPB/RouterAdminProtocolTranslatorPB.java
  3. 51 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/NameserviceManager.java
  4. 52 1
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterAdminServer.java
  5. 4 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClient.java
  6. 65 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/DisabledNameserviceStore.java
  7. 3 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/StateStoreService.java
  8. 68 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/impl/DisabledNameserviceStoreImpl.java
  9. 47 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/DisableNameserviceRequest.java
  10. 50 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/DisableNameserviceResponse.java
  11. 47 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/EnableNameserviceRequest.java
  12. 50 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/EnableNameserviceResponse.java
  13. 30 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/GetDisabledNameservicesRequest.java
  14. 51 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/GetDisabledNameservicesResponse.java
  15. 73 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/DisableNameserviceRequestPBImpl.java
  16. 74 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/DisableNameserviceResponsePBImpl.java
  17. 73 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/EnableNameserviceRequestPBImpl.java
  18. 73 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/EnableNameserviceResponsePBImpl.java
  19. 66 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/GetDisabledNameservicesRequestPBImpl.java
  20. 84 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/GetDisabledNameservicesResponsePBImpl.java
  21. 13 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/BaseRecord.java
  22. 81 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/DisabledNameservice.java
  23. 95 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/impl/pb/DisabledNameservicePBImpl.java
  24. 74 2
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/tools/federation/RouterAdmin.java
  25. 34 1
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/proto/FederationProtocol.proto
  26. 15 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/proto/RouterProtocol.proto
  27. 49 0
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterAdmin.java
  28. 45 3
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterAdminCLI.java
  29. 23 4
      hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/store/driver/TestStateStoreDriverBase.java

+ 67 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/protocolPB/RouterAdminProtocolServerSideTranslatorPB.java

@@ -23,8 +23,14 @@ import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.AddMountTableEntryRequestProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.AddMountTableEntryResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceResponseProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnterSafeModeRequestProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnterSafeModeResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesResponseProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetMountTableEntriesRequestProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetMountTableEntriesResponseProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetSafeModeRequestProto;
@@ -38,8 +44,14 @@ import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProt
 import org.apache.hadoop.hdfs.server.federation.router.RouterAdminServer;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.EnterSafeModeRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.EnterSafeModeResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetSafeModeRequest;
@@ -52,8 +64,14 @@ import org.apache.hadoop.hdfs.server.federation.store.protocol.UpdateMountTableE
 import org.apache.hadoop.hdfs.server.federation.store.protocol.UpdateMountTableEntryResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.AddMountTableEntryRequestPBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.AddMountTableEntryResponsePBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.DisableNameserviceRequestPBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.DisableNameserviceResponsePBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.EnableNameserviceRequestPBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.EnableNameserviceResponsePBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.EnterSafeModeRequestPBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.EnterSafeModeResponsePBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetDisabledNameservicesRequestPBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetDisabledNameservicesResponsePBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetMountTableEntriesRequestPBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetMountTableEntriesResponsePBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetSafeModeRequestPBImpl;
@@ -208,4 +226,53 @@ public class RouterAdminProtocolServerSideTranslatorPB implements
       throw new ServiceException(e);
     }
   }
+
+  @Override
+  public DisableNameserviceResponseProto disableNameservice(
+      RpcController controller, DisableNameserviceRequestProto request)
+      throws ServiceException {
+    try {
+      DisableNameserviceRequest req =
+          new DisableNameserviceRequestPBImpl(request);
+      DisableNameserviceResponse response = server.disableNameservice(req);
+      DisableNameserviceResponsePBImpl responsePB =
+          (DisableNameserviceResponsePBImpl) response;
+      return responsePB.getProto();
+    } catch (IOException e) {
+      throw new ServiceException(e);
+    }
+  }
+
+  @Override
+  public EnableNameserviceResponseProto enableNameservice(
+      RpcController controller, EnableNameserviceRequestProto request)
+          throws ServiceException {
+    try {
+      EnableNameserviceRequest req =
+          new EnableNameserviceRequestPBImpl(request);
+      EnableNameserviceResponse response = server.enableNameservice(req);
+      EnableNameserviceResponsePBImpl responsePB =
+          (EnableNameserviceResponsePBImpl) response;
+      return responsePB.getProto();
+    } catch (IOException e) {
+      throw new ServiceException(e);
+    }
+  }
+
+  @Override
+  public GetDisabledNameservicesResponseProto getDisabledNameservices(
+      RpcController controller, GetDisabledNameservicesRequestProto request)
+      throws ServiceException {
+    try {
+      GetDisabledNameservicesRequest req =
+          new GetDisabledNameservicesRequestPBImpl(request);
+      GetDisabledNameservicesResponse response =
+          server.getDisabledNameservices(req);
+      GetDisabledNameservicesResponsePBImpl responsePB =
+          (GetDisabledNameservicesResponsePBImpl)response;
+      return responsePB.getProto();
+    } catch (IOException e) {
+      throw new ServiceException(e);
+    }
+  }
 }

+ 63 - 1
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/protocolPB/RouterAdminProtocolTranslatorPB.java

@@ -24,8 +24,14 @@ import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.AddMountTableEntryRequestProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.AddMountTableEntryResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceResponseProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnterSafeModeRequestProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnterSafeModeResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesResponseProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetMountTableEntriesRequestProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetMountTableEntriesResponseProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetSafeModeRequestProto;
@@ -37,11 +43,18 @@ import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProt
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.UpdateMountTableEntryRequestProto;
 import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.UpdateMountTableEntryResponseProto;
 import org.apache.hadoop.hdfs.server.federation.resolver.MountTableManager;
+import org.apache.hadoop.hdfs.server.federation.router.NameserviceManager;
 import org.apache.hadoop.hdfs.server.federation.router.RouterStateManager;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.EnterSafeModeRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.EnterSafeModeResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetSafeModeRequest;
@@ -54,7 +67,12 @@ import org.apache.hadoop.hdfs.server.federation.store.protocol.UpdateMountTableE
 import org.apache.hadoop.hdfs.server.federation.store.protocol.UpdateMountTableEntryResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.AddMountTableEntryRequestPBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.AddMountTableEntryResponsePBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.DisableNameserviceRequestPBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.DisableNameserviceResponsePBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.EnableNameserviceRequestPBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.EnableNameserviceResponsePBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.EnterSafeModeResponsePBImpl;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetDisabledNameservicesResponsePBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetMountTableEntriesRequestPBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetMountTableEntriesResponsePBImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.GetSafeModeResponsePBImpl;
@@ -80,7 +98,7 @@ import com.google.protobuf.ServiceException;
 @InterfaceStability.Stable
 public class RouterAdminProtocolTranslatorPB
     implements ProtocolMetaInterface, MountTableManager,
-    Closeable, ProtocolTranslator, RouterStateManager {
+    Closeable, ProtocolTranslator, RouterStateManager, NameserviceManager {
   final private RouterAdminProtocolPB rpcProxy;
 
   public RouterAdminProtocolTranslatorPB(RouterAdminProtocolPB proxy) {
@@ -205,4 +223,48 @@ public class RouterAdminProtocolTranslatorPB
       throw new IOException(ProtobufHelper.getRemoteException(e).getMessage());
     }
   }
+
+  @Override
+  public DisableNameserviceResponse disableNameservice(
+      DisableNameserviceRequest request) throws IOException {
+    DisableNameserviceRequestPBImpl requestPB =
+        (DisableNameserviceRequestPBImpl)request;
+    DisableNameserviceRequestProto proto = requestPB.getProto();
+    try {
+      DisableNameserviceResponseProto response =
+          rpcProxy.disableNameservice(null, proto);
+      return new DisableNameserviceResponsePBImpl(response);
+    } catch (ServiceException e) {
+      throw new IOException(ProtobufHelper.getRemoteException(e).getMessage());
+    }
+  }
+
+  @Override
+  public EnableNameserviceResponse enableNameservice(
+      EnableNameserviceRequest request) throws IOException {
+    EnableNameserviceRequestPBImpl requestPB =
+        (EnableNameserviceRequestPBImpl)request;
+    EnableNameserviceRequestProto proto = requestPB.getProto();
+    try {
+      EnableNameserviceResponseProto response =
+          rpcProxy.enableNameservice(null, proto);
+      return new EnableNameserviceResponsePBImpl(response);
+    } catch (ServiceException e) {
+      throw new IOException(ProtobufHelper.getRemoteException(e).getMessage());
+    }
+  }
+
+  @Override
+  public GetDisabledNameservicesResponse getDisabledNameservices(
+      GetDisabledNameservicesRequest request) throws IOException {
+    GetDisabledNameservicesRequestProto proto =
+        GetDisabledNameservicesRequestProto.newBuilder().build();
+    try {
+      GetDisabledNameservicesResponseProto response =
+          rpcProxy.getDisabledNameservices(null, proto);
+      return new GetDisabledNameservicesResponsePBImpl(response);
+    } catch (ServiceException e) {
+      throw new IOException(ProtobufHelper.getRemoteException(e).getMessage());
+    }
+  }
 }

+ 51 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/NameserviceManager.java

@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.router;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesResponse;
+
+/**
+ * Interface for enable/disable name service.
+ */
+public interface NameserviceManager {
+
+  /**
+   * Disable a name service.
+   */
+  DisableNameserviceResponse disableNameservice(
+      DisableNameserviceRequest request) throws IOException;
+
+  /**
+   * Enable a name service.
+   */
+  EnableNameserviceResponse enableNameservice(EnableNameserviceRequest request)
+      throws IOException;
+
+  /**
+   * Get the list of disabled name service.
+   */
+  GetDisabledNameservicesResponse getDisabledNameservices(
+      GetDisabledNameservicesRequest request) throws IOException;
+}

+ 52 - 1
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterAdminServer.java

@@ -22,6 +22,7 @@ import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PERMISSIONS_ENABLED_KEY;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.util.Set;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hdfs.DFSConfigKeys;
@@ -29,11 +30,18 @@ import org.apache.hadoop.hdfs.protocol.proto.RouterProtocolProtos.RouterAdminPro
 import org.apache.hadoop.hdfs.protocolPB.RouterAdminProtocolPB;
 import org.apache.hadoop.hdfs.protocolPB.RouterAdminProtocolServerSideTranslatorPB;
 import org.apache.hadoop.hdfs.server.federation.resolver.MountTableManager;
+import org.apache.hadoop.hdfs.server.federation.store.DisabledNameserviceStore;
 import org.apache.hadoop.hdfs.server.federation.store.MountTableStore;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.EnterSafeModeRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.EnterSafeModeResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetSafeModeRequest;
@@ -62,7 +70,7 @@ import com.google.protobuf.BlockingService;
  * router. It is created, started, and stopped by {@link Router}.
  */
 public class RouterAdminServer extends AbstractService
-    implements MountTableManager, RouterStateManager {
+    implements MountTableManager, RouterStateManager, NameserviceManager {
 
   private static final Logger LOG =
       LoggerFactory.getLogger(RouterAdminServer.class);
@@ -73,6 +81,8 @@ public class RouterAdminServer extends AbstractService
 
   private MountTableStore mountTableStore;
 
+  private DisabledNameserviceStore disabledStore;
+
   /** The Admin server that listens to requests from clients. */
   private final Server adminServer;
   private final InetSocketAddress adminAddress;
@@ -166,6 +176,19 @@ public class RouterAdminServer extends AbstractService
     return this.mountTableStore;
   }
 
+  private DisabledNameserviceStore getDisabledNameserviceStore()
+      throws IOException {
+    if (this.disabledStore == null) {
+      this.disabledStore = router.getStateStore().getRegisteredRecordStore(
+          DisabledNameserviceStore.class);
+      if (this.disabledStore == null) {
+        throw new IOException(
+            "Disabled Nameservice state store is not available.");
+      }
+    }
+    return this.disabledStore;
+  }
+
   /**
    * Get the RPC address of the admin service.
    * @return Administration service RPC address.
@@ -256,6 +279,34 @@ public class RouterAdminServer extends AbstractService
             && !serverInSafeMode);
   }
 
+  @Override
+  public DisableNameserviceResponse disableNameservice(
+      DisableNameserviceRequest request) throws IOException {
+    // TODO check permissions
+    String nsId = request.getNameServiceId();
+    // TODO check that the name service exists
+    boolean success = getDisabledNameserviceStore().disableNameservice(nsId);
+    return DisableNameserviceResponse.newInstance(success);
+  }
+
+  @Override
+  public EnableNameserviceResponse enableNameservice(
+      EnableNameserviceRequest request) throws IOException {
+    // TODO check permissions
+    String nsId = request.getNameServiceId();
+    // TODO check that the name service exists
+    boolean success = getDisabledNameserviceStore().enableNameservice(nsId);
+    return EnableNameserviceResponse.newInstance(success);
+  }
+
+  @Override
+  public GetDisabledNameservicesResponse getDisabledNameservices(
+      GetDisabledNameservicesRequest request) throws IOException {
+    // TODO check permissions
+    Set<String> nsIds = getDisabledNameserviceStore().getDisabledNameservices();
+    return GetDisabledNameservicesResponse.newInstance(nsIds);
+  }
+
   /**
    * Get a new permission checker used for making mount table access
    * control. This method will be invoked during each RPC call in router

+ 4 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClient.java

@@ -73,6 +73,10 @@ public class RouterClient implements Closeable {
     return proxy;
   }
 
+  public NameserviceManager getNameserviceManager() {
+    return proxy;
+  }
+
   @Override
   public synchronized void close() throws IOException {
     RPC.stopProxy(proxy);

+ 65 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/DisabledNameserviceStore.java

@@ -0,0 +1,65 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreDriver;
+import org.apache.hadoop.hdfs.server.federation.store.records.DisabledNameservice;
+
+/**
+ * State store record to track disabled name services.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Evolving
+public abstract class DisabledNameserviceStore
+    extends CachedRecordStore<DisabledNameservice> {
+
+  public DisabledNameserviceStore(StateStoreDriver driver) {
+    super(DisabledNameservice.class, driver);
+  }
+
+  /**
+   * Disable a name service.
+   *
+   * @param nsId Identifier of the name service.
+   * @return If the name service was successfully disabled.
+   * @throws IOException If the state store could not be queried.
+   */
+  public abstract boolean disableNameservice(String nsId) throws IOException;
+
+  /**
+   * Enable a name service.
+   *
+   * @param nsId Identifier of the name service.
+   * @return If the name service was successfully brought back.
+   * @throws IOException If the state store could not be queried.
+   */
+  public abstract boolean enableNameservice(String nsId) throws IOException;
+
+  /**
+   * Get a list of disabled name services.
+   *
+   * @return List of disabled name services.
+   * @throws IOException If the state store could not be queried.
+   */
+  public abstract Set<String> getDisabledNameservices() throws IOException;
+}

+ 3 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/StateStoreService.java

@@ -37,6 +37,7 @@ import org.apache.hadoop.hdfs.server.federation.metrics.StateStoreMBean;
 import org.apache.hadoop.hdfs.server.federation.metrics.StateStoreMetrics;
 import org.apache.hadoop.hdfs.server.federation.router.RBFConfigKeys;
 import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreDriver;
+import org.apache.hadoop.hdfs.server.federation.store.impl.DisabledNameserviceStoreImpl;
 import org.apache.hadoop.hdfs.server.federation.store.impl.MembershipStoreImpl;
 import org.apache.hadoop.hdfs.server.federation.store.impl.MountTableStoreImpl;
 import org.apache.hadoop.hdfs.server.federation.store.impl.RouterStoreImpl;
@@ -75,6 +76,7 @@ import com.google.common.annotations.VisibleForTesting;
  * See {@link org.apache.hadoop.fs.viewfs.ViewFs ViewFs}.
  * <li>{@link RebalancerStore}: Log of the rebalancing operations.
  * <li>{@link RouterStore}: Router state in the federation.
+ * <li>{@link DisabledNameserviceStore}: Disabled name services.
  * <li>{@link TokenStore}: Tokens in the federation.
  * </ul>
  */
@@ -152,6 +154,7 @@ public class StateStoreService extends CompositeService {
     addRecordStore(MembershipStoreImpl.class);
     addRecordStore(MountTableStoreImpl.class);
     addRecordStore(RouterStoreImpl.class);
+    addRecordStore(DisabledNameserviceStoreImpl.class);
 
     // Check the connection to the State Store periodically
     this.monitorService = new StateStoreConnectionMonitorService(this);

+ 68 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/impl/DisabledNameserviceStoreImpl.java

@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.impl;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.hdfs.server.federation.store.DisabledNameserviceStore;
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreDriver;
+import org.apache.hadoop.hdfs.server.federation.store.records.DisabledNameservice;
+
+/**
+ * Implementation of {@link DisabledNameserviceStore}.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Evolving
+public class DisabledNameserviceStoreImpl extends DisabledNameserviceStore {
+
+  public DisabledNameserviceStoreImpl(StateStoreDriver driver) {
+    super(driver);
+  }
+
+  @Override
+  public boolean disableNameservice(String nsId)
+      throws IOException {
+
+    DisabledNameservice record =
+        DisabledNameservice.newInstance(nsId);
+    return getDriver().put(record, false, false);
+  }
+
+  @Override
+  public boolean enableNameservice(String nsId)
+      throws IOException {
+
+    DisabledNameservice record =
+        DisabledNameservice.newInstance(nsId);
+    return getDriver().remove(record);
+  }
+
+  @Override
+  public Set<String> getDisabledNameservices() throws IOException {
+    Set<String> disabledNameservices = new TreeSet<>();
+    for (DisabledNameservice record : getCachedRecords()) {
+      String nsId = record.getNameserviceId();
+      disabledNameservices.add(nsId);
+    }
+    return disabledNameservices;
+  }
+}

+ 47 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/DisableNameserviceRequest.java

@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol;
+
+import org.apache.hadoop.classification.InterfaceAudience.Public;
+import org.apache.hadoop.classification.InterfaceStability.Unstable;
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreSerializer;
+
+/**
+ * API request for disabling a name service and updating its state in the
+ * State Store.
+ */
+public abstract class DisableNameserviceRequest {
+
+  public static DisableNameserviceRequest newInstance() {
+    return StateStoreSerializer.newRecord(DisableNameserviceRequest.class);
+  }
+
+  public static DisableNameserviceRequest newInstance(String nsId) {
+    DisableNameserviceRequest request = newInstance();
+    request.setNameServiceId(nsId);
+    return request;
+  }
+
+  @Public
+  @Unstable
+  public abstract String getNameServiceId();
+
+  @Public
+  @Unstable
+  public abstract void setNameServiceId(String nsId);
+}

+ 50 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/DisableNameserviceResponse.java

@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol;
+
+import java.io.IOException;
+
+import org.apache.hadoop.classification.InterfaceAudience.Public;
+import org.apache.hadoop.classification.InterfaceStability.Unstable;
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreSerializer;
+
+/**
+ * API response for disabling a name service and updating its state in the
+ * State Store.
+ */
+public abstract class DisableNameserviceResponse {
+
+  public static DisableNameserviceResponse newInstance() throws IOException {
+    return StateStoreSerializer.newRecord(DisableNameserviceResponse.class);
+  }
+
+  public static DisableNameserviceResponse newInstance(boolean status)
+      throws IOException {
+    DisableNameserviceResponse response = newInstance();
+    response.setStatus(status);
+    return response;
+  }
+
+  @Public
+  @Unstable
+  public abstract boolean getStatus();
+
+  @Public
+  @Unstable
+  public abstract void setStatus(boolean result);
+}

+ 47 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/EnableNameserviceRequest.java

@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol;
+
+import org.apache.hadoop.classification.InterfaceAudience.Public;
+import org.apache.hadoop.classification.InterfaceStability.Unstable;
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreSerializer;
+
+/**
+ * API request for enabling a name service and updating its state in the
+ * State Store.
+ */
+public abstract class EnableNameserviceRequest {
+
+  public static EnableNameserviceRequest newInstance() {
+    return StateStoreSerializer.newRecord(EnableNameserviceRequest.class);
+  }
+
+  public static EnableNameserviceRequest newInstance(String nsId) {
+    EnableNameserviceRequest request = newInstance();
+    request.setNameServiceId(nsId);
+    return request;
+  }
+
+  @Public
+  @Unstable
+  public abstract String getNameServiceId();
+
+  @Public
+  @Unstable
+  public abstract void setNameServiceId(String nsId);
+}

+ 50 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/EnableNameserviceResponse.java

@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol;
+
+import java.io.IOException;
+
+import org.apache.hadoop.classification.InterfaceAudience.Public;
+import org.apache.hadoop.classification.InterfaceStability.Unstable;
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreSerializer;
+
+/**
+ * API response for enabling a name service and updating its state in the
+ * State Store.
+ */
+public abstract class EnableNameserviceResponse {
+
+  public static EnableNameserviceResponse newInstance() throws IOException {
+    return StateStoreSerializer.newRecord(EnableNameserviceResponse.class);
+  }
+
+  public static EnableNameserviceResponse newInstance(boolean status)
+      throws IOException {
+    EnableNameserviceResponse response = newInstance();
+    response.setStatus(status);
+    return response;
+  }
+
+  @Public
+  @Unstable
+  public abstract boolean getStatus();
+
+  @Public
+  @Unstable
+  public abstract void setStatus(boolean result);
+}

+ 30 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/GetDisabledNameservicesRequest.java

@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol;
+
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreSerializer;
+
+/**
+ * API request for getting the disabled name services.
+ */
+public abstract class GetDisabledNameservicesRequest {
+
+  public static GetDisabledNameservicesRequest newInstance() {
+    return StateStoreSerializer.newRecord(GetDisabledNameservicesRequest.class);
+  }
+}

+ 51 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/GetDisabledNameservicesResponse.java

@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol;
+
+import java.util.Set;
+
+import org.apache.hadoop.classification.InterfaceAudience.Public;
+import org.apache.hadoop.classification.InterfaceStability.Unstable;
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreSerializer;
+
+/**
+ * API response for getting the disabled nameservices in the state store.
+ */
+public abstract class GetDisabledNameservicesResponse {
+
+  public static GetDisabledNameservicesResponse newInstance() {
+    return StateStoreSerializer.newRecord(
+        GetDisabledNameservicesResponse.class);
+  }
+
+  public static GetDisabledNameservicesResponse newInstance(
+      Set<String> nsIds) {
+    GetDisabledNameservicesResponse response = newInstance();
+    response.setNameservices(nsIds);
+    return response;
+  }
+
+  @Public
+  @Unstable
+  public abstract Set<String> getNameservices();
+
+  @Public
+  @Unstable
+  public abstract void setNameservices(Set<String> nameservices);
+
+}

+ 73 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/DisableNameserviceRequestPBImpl.java

@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceRequestProto.Builder;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceRequestProtoOrBuilder;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.records.impl.pb.PBRecord;
+
+import com.google.protobuf.Message;
+
+/**
+ * Protobuf implementation of the state store API object
+ * DisableNameserviceRequest.
+ */
+public class DisableNameserviceRequestPBImpl extends DisableNameserviceRequest
+    implements PBRecord {
+
+  private FederationProtocolPBTranslator<DisableNameserviceRequestProto,
+      Builder, DisableNameserviceRequestProtoOrBuilder> translator =
+          new FederationProtocolPBTranslator<>(
+              DisableNameserviceRequestProto.class);
+
+  public DisableNameserviceRequestPBImpl() {
+  }
+
+  public DisableNameserviceRequestPBImpl(DisableNameserviceRequestProto proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public DisableNameserviceRequestProto getProto() {
+    return translator.build();
+  }
+
+  @Override
+  public void setProto(Message proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public void readInstance(String base64String) throws IOException {
+    this.translator.readInstance(base64String);
+  }
+
+  @Override
+  public String getNameServiceId() {
+    return this.translator.getProtoOrBuilder().getNameServiceId();
+  }
+
+  @Override
+  public void setNameServiceId(String nsId) {
+    this.translator.getBuilder().setNameServiceId(nsId);
+  }
+}

+ 74 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/DisableNameserviceResponsePBImpl.java

@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceResponseProto.Builder;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisableNameserviceResponseProtoOrBuilder;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.records.impl.pb.PBRecord;
+
+import com.google.protobuf.Message;
+
+/**
+ * Protobuf implementation of the state store API object
+ * {@link DisableNameserviceResponse}.
+ */
+public class DisableNameserviceResponsePBImpl
+    extends DisableNameserviceResponse implements PBRecord {
+
+  private FederationProtocolPBTranslator<DisableNameserviceResponseProto,
+      Builder, DisableNameserviceResponseProtoOrBuilder> translator =
+          new FederationProtocolPBTranslator<>(
+              DisableNameserviceResponseProto.class);
+
+  public DisableNameserviceResponsePBImpl() {
+  }
+
+  public DisableNameserviceResponsePBImpl(
+      DisableNameserviceResponseProto proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public DisableNameserviceResponseProto getProto() {
+    return translator.build();
+  }
+
+  @Override
+  public void setProto(Message proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public void readInstance(String base64String) throws IOException {
+    this.translator.readInstance(base64String);
+  }
+
+  @Override
+  public boolean getStatus() {
+    return this.translator.getProtoOrBuilder().getStatus();
+  }
+
+  @Override
+  public void setStatus(boolean status) {
+    this.translator.getBuilder().setStatus(status);
+  }
+}

+ 73 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/EnableNameserviceRequestPBImpl.java

@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceRequestProto.Builder;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceRequestProtoOrBuilder;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.records.impl.pb.PBRecord;
+
+import com.google.protobuf.Message;
+
+/**
+ * Protobuf implementation of the state store API object
+ * EnableNameserviceRequest.
+ */
+public class EnableNameserviceRequestPBImpl extends EnableNameserviceRequest
+    implements PBRecord {
+
+  private FederationProtocolPBTranslator<EnableNameserviceRequestProto,
+      Builder, EnableNameserviceRequestProtoOrBuilder> translator =
+          new FederationProtocolPBTranslator<>(
+              EnableNameserviceRequestProto.class);
+
+  public EnableNameserviceRequestPBImpl() {
+  }
+
+  public EnableNameserviceRequestPBImpl(EnableNameserviceRequestProto proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public EnableNameserviceRequestProto getProto() {
+    return translator.build();
+  }
+
+  @Override
+  public void setProto(Message proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public void readInstance(String base64String) throws IOException {
+    this.translator.readInstance(base64String);
+  }
+
+  @Override
+  public String getNameServiceId() {
+    return this.translator.getProtoOrBuilder().getNameServiceId();
+  }
+
+  @Override
+  public void setNameServiceId(String nsId) {
+    this.translator.getBuilder().setNameServiceId(nsId);
+  }
+}

+ 73 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/EnableNameserviceResponsePBImpl.java

@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceResponseProto.Builder;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.EnableNameserviceResponseProtoOrBuilder;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.records.impl.pb.PBRecord;
+
+import com.google.protobuf.Message;
+
+/**
+ * Protobuf implementation of the state store API object
+ * EnableNameserviceResponse.
+ */
+public class EnableNameserviceResponsePBImpl extends EnableNameserviceResponse
+    implements PBRecord {
+
+  private FederationProtocolPBTranslator<EnableNameserviceResponseProto,
+      Builder, EnableNameserviceResponseProtoOrBuilder> translator =
+          new FederationProtocolPBTranslator<>(
+              EnableNameserviceResponseProto.class);
+
+  public EnableNameserviceResponsePBImpl() {
+  }
+
+  public EnableNameserviceResponsePBImpl(EnableNameserviceResponseProto proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public EnableNameserviceResponseProto getProto() {
+    return translator.build();
+  }
+
+  @Override
+  public void setProto(Message proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public void readInstance(String base64String) throws IOException {
+    this.translator.readInstance(base64String);
+  }
+
+  @Override
+  public boolean getStatus() {
+    return this.translator.getProtoOrBuilder().getStatus();
+  }
+
+  @Override
+  public void setStatus(boolean status) {
+    this.translator.getBuilder().setStatus(status);
+  }
+}

+ 66 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/GetDisabledNameservicesRequestPBImpl.java

@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesRequestProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesRequestProto.Builder;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesRequestProtoOrBuilder;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesRequest;
+import org.apache.hadoop.hdfs.server.federation.store.records.impl.pb.PBRecord;
+
+import com.google.protobuf.Message;
+
+/**
+ * Protobuf implementation of the state store API object
+ * GetDisabledNameservicesRequest.
+ */
+public class GetDisabledNameservicesRequestPBImpl
+    extends GetDisabledNameservicesRequest implements PBRecord {
+
+  private FederationProtocolPBTranslator<GetDisabledNameservicesRequestProto,
+      Builder, GetDisabledNameservicesRequestProtoOrBuilder> translator =
+          new FederationProtocolPBTranslator<>(
+              GetDisabledNameservicesRequestProto.class);
+
+  public GetDisabledNameservicesRequestPBImpl() {
+    // As this request has no parameter, we need to initialize it
+    this.translator.getBuilder();
+  }
+
+  public GetDisabledNameservicesRequestPBImpl(
+      GetDisabledNameservicesRequestProto proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public GetDisabledNameservicesRequestProto getProto() {
+    return translator.build();
+  }
+
+  @Override
+  public void setProto(Message proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public void readInstance(String base64String) throws IOException {
+    this.translator.readInstance(base64String);
+  }
+}

+ 84 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/protocol/impl/pb/GetDisabledNameservicesResponsePBImpl.java

@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesResponseProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesResponseProto.*;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.GetDisabledNameservicesResponseProtoOrBuilder;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesResponse;
+import org.apache.hadoop.hdfs.server.federation.store.records.impl.pb.PBRecord;
+
+import com.google.protobuf.Message;
+
+/**
+ * Protobuf implementation of the state store API object
+ * GetDisabledNameservicesResponse.
+ */
+public class GetDisabledNameservicesResponsePBImpl
+    extends GetDisabledNameservicesResponse implements PBRecord {
+
+  private FederationProtocolPBTranslator<GetDisabledNameservicesResponseProto,
+      Builder, GetDisabledNameservicesResponseProtoOrBuilder> translator =
+          new FederationProtocolPBTranslator<
+              GetDisabledNameservicesResponseProto, Builder,
+              GetDisabledNameservicesResponseProtoOrBuilder>(
+                  GetDisabledNameservicesResponseProto.class);
+
+  public GetDisabledNameservicesResponsePBImpl() {
+  }
+
+  public GetDisabledNameservicesResponsePBImpl(
+      GetDisabledNameservicesResponseProto proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public GetDisabledNameservicesResponseProto getProto() {
+    return this.translator.build();
+  }
+
+  @Override
+  public void setProto(Message proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public void readInstance(String base64String) throws IOException {
+    this.translator.readInstance(base64String);
+  }
+
+  @Override
+  public Set<String> getNameservices() {
+    List<String> nsIds =
+        this.translator.getProtoOrBuilder().getNameServiceIdsList();
+    return new TreeSet<>(nsIds);
+  }
+
+  @Override
+  public void setNameservices(Set<String> nameservices) {
+    this.translator.getBuilder().clearNameServiceIds();
+    for (String nsId : nameservices) {
+      this.translator.getBuilder().addNameServiceIds(nsId);
+    }
+  }
+}

+ 13 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/BaseRecord.java

@@ -21,6 +21,8 @@ import java.util.Map;
 
 import org.apache.hadoop.util.Time;
 
+import com.google.common.annotations.VisibleForTesting;
+
 /**
  * Abstract base of a data record in the StateStore. All StateStore records are
  * derived from this class. Data records are persisted in the data store and
@@ -109,6 +111,17 @@ public abstract class BaseRecord implements Comparable<BaseRecord> {
     return generateMashupKey(getPrimaryKeys());
   }
 
+  /**
+   * If the record has fields others than the primary keys. This is used by
+   * TestStateStoreDriverBase to skip the modification check.
+   *
+   * @return If the record has more fields.
+   */
+  @VisibleForTesting
+  public boolean hasOtherFields() {
+    return true;
+  }
+
   /**
    * Generates a cache key from a map of values.
    *

+ 81 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/DisabledNameservice.java

@@ -0,0 +1,81 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.records;
+
+import java.io.IOException;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.hadoop.hdfs.server.federation.store.driver.StateStoreSerializer;
+
+/**
+ * Data record indicating a specific name service ID has been disabled and
+ * is no longer valid. Allows quick disabling of name services.
+ */
+public abstract class DisabledNameservice extends BaseRecord {
+
+  public DisabledNameservice() {
+    super();
+  }
+
+  public static DisabledNameservice newInstance() throws IOException {
+    DisabledNameservice record =
+        StateStoreSerializer.newRecord(DisabledNameservice.class);
+    record.init();
+    return record;
+  }
+
+  public static DisabledNameservice newInstance(String nsId)
+      throws IOException {
+    DisabledNameservice record = newInstance();
+    record.setNameserviceId(nsId);
+    return record;
+  }
+
+  /**
+   * Get the identifier of the name service to disable.
+   *
+   * @return Identifier of the name service to disable.
+   */
+  public abstract String getNameserviceId();
+
+  /**
+   * Set the identifier of the name service to disable.
+   *
+   * @param nameServiceId Identifier of the name service to disable.
+   */
+  public abstract void setNameserviceId(String nameServiceId);
+
+  @Override
+  public SortedMap<String, String> getPrimaryKeys() {
+    SortedMap<String, String> keyMap = new TreeMap<>();
+    keyMap.put("nameServiceId", this.getNameserviceId());
+    return keyMap;
+  }
+
+  @Override
+  public boolean hasOtherFields() {
+    // We don't have fields other than the primary keys
+    return false;
+  }
+
+  @Override
+  public long getExpirationMs() {
+    return -1;
+  }
+}

+ 95 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/impl/pb/DisabledNameservicePBImpl.java

@@ -0,0 +1,95 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.federation.store.records.impl.pb;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisabledNameserviceRecordProto;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisabledNameserviceRecordProto.Builder;
+import org.apache.hadoop.hdfs.federation.protocol.proto.HdfsServerFederationProtos.DisabledNameserviceRecordProtoOrBuilder;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.impl.pb.FederationProtocolPBTranslator;
+import org.apache.hadoop.hdfs.server.federation.store.records.DisabledNameservice;
+
+import com.google.protobuf.Message;
+
+/**
+ * Protobuf implementation of the {@link DisabledNameservice} record.
+ */
+public class DisabledNameservicePBImpl extends DisabledNameservice
+    implements PBRecord {
+
+  private FederationProtocolPBTranslator<DisabledNameserviceRecordProto,
+      Builder, DisabledNameserviceRecordProtoOrBuilder> translator =
+          new FederationProtocolPBTranslator<
+              DisabledNameserviceRecordProto, Builder,
+              DisabledNameserviceRecordProtoOrBuilder>(
+                  DisabledNameserviceRecordProto.class);
+
+  public DisabledNameservicePBImpl() {
+  }
+
+  public DisabledNameservicePBImpl(
+      DisabledNameserviceRecordProto proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public DisabledNameserviceRecordProto getProto() {
+    return this.translator.build();
+  }
+
+  @Override
+  public void setProto(Message proto) {
+    this.translator.setProto(proto);
+  }
+
+  @Override
+  public void readInstance(String base64String) throws IOException {
+    this.translator.readInstance(base64String);
+  }
+
+  @Override
+  public String getNameserviceId() {
+    return this.translator.getProtoOrBuilder().getNameServiceId();
+  }
+
+  @Override
+  public void setNameserviceId(String nameServiceId) {
+    this.translator.getBuilder().setNameServiceId(nameServiceId);
+  }
+
+  @Override
+  public void setDateModified(long time) {
+    this.translator.getBuilder().setDateModified(time);
+  }
+
+  @Override
+  public long getDateModified() {
+    return this.translator.getProtoOrBuilder().getDateModified();
+  }
+
+  @Override
+  public void setDateCreated(long time) {
+    this.translator.getBuilder().setDateCreated(time);
+  }
+
+  @Override
+  public long getDateCreated() {
+    return this.translator.getProtoOrBuilder().getDateCreated();
+  }
+}

+ 74 - 2
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/tools/federation/RouterAdmin.java

@@ -32,14 +32,21 @@ import org.apache.hadoop.hdfs.protocol.HdfsConstants;
 import org.apache.hadoop.hdfs.server.federation.resolver.MountTableManager;
 import org.apache.hadoop.hdfs.server.federation.resolver.RemoteLocation;
 import org.apache.hadoop.hdfs.server.federation.resolver.order.DestinationOrder;
-import org.apache.hadoop.hdfs.server.federation.router.RouterClient;
+import org.apache.hadoop.hdfs.server.federation.router.NameserviceManager;
 import org.apache.hadoop.hdfs.server.federation.router.RBFConfigKeys;
+import org.apache.hadoop.hdfs.server.federation.router.RouterClient;
 import org.apache.hadoop.hdfs.server.federation.router.RouterQuotaUsage;
 import org.apache.hadoop.hdfs.server.federation.router.RouterStateManager;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.EnterSafeModeRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.EnterSafeModeResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetSafeModeRequest;
@@ -95,7 +102,9 @@ public class RouterAdmin extends Configured implements Tool {
         + "\t[-setQuota <path> -nsQuota <nsQuota> -ssQuota "
         + "<quota in bytes or quota size string>]\n"
         + "\t[-clrQuota <path>]\n"
-        + "\t[-safemode enter | leave | get]\n";
+        + "\t[-safemode enter | leave | get]\n"
+        + "\t[-nameservice enable | disable <nameservice>]\n"
+        + "\t[-getDisabledNameservices]\n";
 
     System.out.println(usage);
   }
@@ -143,6 +152,12 @@ public class RouterAdmin extends Configured implements Tool {
         printUsage();
         return exitCode;
       }
+    } else if ("-nameservice".equalsIgnoreCase(cmd)) {
+      if (argv.length < 3) {
+        System.err.println("Not enough parameters specificed for cmd " + cmd);
+        printUsage();
+        return exitCode;
+      }
     }
 
     // Initialize RouterClient
@@ -190,6 +205,12 @@ public class RouterAdmin extends Configured implements Tool {
         }
       } else if ("-safemode".equals(cmd)) {
         manageSafeMode(argv[i]);
+      } else if ("-nameservice".equals(cmd)) {
+        String subcmd = argv[i];
+        String nsId = argv[i + 1];
+        manageNameservice(subcmd, nsId);
+      } else if ("-getDisabledNameservices".equals(cmd)) {
+        getDisabledNameservices();
       } else {
         printUsage();
         return exitCode;
@@ -611,6 +632,57 @@ public class RouterAdmin extends Configured implements Tool {
     return response.isInSafeMode();
   }
 
+  /**
+   * Manage the name service: enabling/disabling.
+   * @param cmd Input command, disable or enable.
+   * @throws IOException
+   */
+  private void manageNameservice(String cmd, String nsId) throws IOException {
+    if (cmd.equals("enable")) {
+      if (enableNameservice(nsId)) {
+        System.out.println("Successfully enabled nameservice " + nsId);
+      } else {
+        System.err.println("Cannot enable " + nsId);
+      }
+    } else if (cmd.equals("disable")) {
+      if (disableNameservice(nsId)) {
+        System.out.println("Successfully disabled nameservice " + nsId);
+      } else {
+        System.err.println("Cannot disable " + nsId);
+      }
+    } else {
+      throw new IllegalArgumentException("Unknown command: " + cmd);
+    }
+  }
+
+  private boolean disableNameservice(String nsId) throws IOException {
+    NameserviceManager nameserviceManager = client.getNameserviceManager();
+    DisableNameserviceResponse response =
+        nameserviceManager.disableNameservice(
+            DisableNameserviceRequest.newInstance(nsId));
+    return response.getStatus();
+  }
+
+  private boolean enableNameservice(String nsId) throws IOException {
+    NameserviceManager nameserviceManager = client.getNameserviceManager();
+    EnableNameserviceResponse response =
+        nameserviceManager.enableNameservice(
+            EnableNameserviceRequest.newInstance(nsId));
+    return response.getStatus();
+  }
+
+  private void getDisabledNameservices() throws IOException {
+    NameserviceManager nameserviceManager = client.getNameserviceManager();
+    GetDisabledNameservicesRequest request =
+        GetDisabledNameservicesRequest.newInstance();
+    GetDisabledNameservicesResponse response =
+        nameserviceManager.getDisabledNameservices(request);
+    System.out.println("List of disabled nameservices:");
+    for (String nsId : response.getNameservices()) {
+      System.out.println(nsId);
+    }
+  }
+
   /**
    * Inner class that stores ACL info of mount table.
    */

+ 34 - 1
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/proto/FederationProtocol.proto

@@ -242,4 +242,37 @@ message GetSafeModeRequestProto {
 
 message GetSafeModeResponseProto {
   optional bool isInSafeMode = 1;
-}
+}
+
+/////////////////////////////////////////////////
+// Disabled Nameservice State
+/////////////////////////////////////////////////
+
+message DisabledNameserviceRecordProto {
+  optional uint64 dateCreated = 1;
+  optional uint64 dateModified = 2;
+  optional string nameServiceId = 3;
+}
+
+message DisableNameserviceRequestProto {
+  optional string nameServiceId = 1;
+}
+
+message DisableNameserviceResponseProto {
+  optional bool status = 1;
+}
+
+message EnableNameserviceRequestProto {
+  optional string nameServiceId = 1;
+}
+
+message EnableNameserviceResponseProto {
+  optional bool status = 1;
+}
+
+message GetDisabledNameservicesRequestProto {
+}
+
+message GetDisabledNameservicesResponseProto {
+  repeated string nameServiceIds = 1;
+}

+ 15 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/proto/RouterProtocol.proto

@@ -59,4 +59,19 @@ service RouterAdminProtocolService {
    * Verify if current Router state is safe mode state.
    */
   rpc getSafeMode(GetSafeModeRequestProto) returns (GetSafeModeResponseProto);
+
+  /**
+   * Disable a name service.
+   */
+  rpc disableNameservice(DisableNameserviceRequestProto) returns (DisableNameserviceResponseProto);
+
+  /**
+   * Enable a name service.
+   */
+  rpc enableNameservice(EnableNameserviceRequestProto) returns (EnableNameserviceResponseProto);
+
+  /**
+   * Get the list of disabled name services.
+   */
+  rpc getDisabledNameservices(GetDisabledNameservicesRequestProto) returns (GetDisabledNameservicesResponseProto);
 }

+ 49 - 0
hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterAdmin.java

@@ -26,6 +26,7 @@ import static org.junit.Assert.assertTrue;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hdfs.server.federation.RouterConfigBuilder;
@@ -35,9 +36,16 @@ import org.apache.hadoop.hdfs.server.federation.resolver.MountTableManager;
 import org.apache.hadoop.hdfs.server.federation.resolver.RemoteLocation;
 import org.apache.hadoop.hdfs.server.federation.resolver.order.DestinationOrder;
 import org.apache.hadoop.hdfs.server.federation.store.StateStoreService;
+import org.apache.hadoop.hdfs.server.federation.store.impl.DisabledNameserviceStoreImpl;
 import org.apache.hadoop.hdfs.server.federation.store.impl.MountTableStoreImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.AddMountTableEntryResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.DisableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.EnableNameserviceResponse;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesRequest;
+import org.apache.hadoop.hdfs.server.federation.store.protocol.GetDisabledNameservicesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesResponse;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.RemoveMountTableEntryRequest;
@@ -337,4 +345,45 @@ public class TestRouterAdmin {
         mountTable.getMountTableEntries(request);
     return response.getEntries();
   }
+
+  @Test
+  public void testNameserviceManager() throws IOException {
+
+    RouterClient client = routerContext.getAdminClient();
+    NameserviceManager nsManager = client.getNameserviceManager();
+
+    // There shouldn't be any name service disabled
+    Set<String> disabled = getDisabledNameservices(nsManager);
+    assertTrue(disabled.isEmpty());
+
+    // Disable one and see it
+    DisableNameserviceRequest disableReq =
+        DisableNameserviceRequest.newInstance("ns0");
+    DisableNameserviceResponse disableResp =
+        nsManager.disableNameservice(disableReq);
+    assertTrue(disableResp.getStatus());
+    // Refresh the cache
+    disabled = getDisabledNameservices(nsManager);
+    assertEquals(1, disabled.size());
+    assertTrue(disabled.contains("ns0"));
+
+    // Enable one and we should have no disabled name services
+    EnableNameserviceRequest enableReq =
+        EnableNameserviceRequest.newInstance("ns0");
+    EnableNameserviceResponse enableResp =
+        nsManager.enableNameservice(enableReq);
+    assertTrue(enableResp.getStatus());
+    disabled = getDisabledNameservices(nsManager);
+    assertTrue(disabled.isEmpty());
+  }
+
+  private Set<String> getDisabledNameservices(NameserviceManager nsManager)
+      throws IOException {
+    stateStore.loadCache(DisabledNameserviceStoreImpl.class, true);
+    GetDisabledNameservicesRequest getReq =
+        GetDisabledNameservicesRequest.newInstance();
+    GetDisabledNameservicesResponse response =
+        nsManager.getDisabledNameservices(getReq);
+    return response.getNameservices();
+  }
 }

+ 45 - 3
hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterAdminCLI.java

@@ -22,20 +22,20 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayOutputStream;
-
 import java.io.PrintStream;
 import java.net.InetSocketAddress;
 import java.util.List;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.hdfs.protocol.HdfsConstants;
-import org.apache.hadoop.hdfs.server.federation.RouterConfigBuilder;
 import org.apache.hadoop.hdfs.server.federation.MiniRouterDFSCluster.RouterContext;
+import org.apache.hadoop.hdfs.server.federation.RouterConfigBuilder;
 import org.apache.hadoop.hdfs.server.federation.StateStoreDFSCluster;
 import org.apache.hadoop.hdfs.server.federation.resolver.MountTableManager;
 import org.apache.hadoop.hdfs.server.federation.resolver.RemoteLocation;
 import org.apache.hadoop.hdfs.server.federation.resolver.order.DestinationOrder;
 import org.apache.hadoop.hdfs.server.federation.store.StateStoreService;
+import org.apache.hadoop.hdfs.server.federation.store.impl.DisabledNameserviceStoreImpl;
 import org.apache.hadoop.hdfs.server.federation.store.impl.MountTableStoreImpl;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesRequest;
 import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesResponse;
@@ -65,7 +65,9 @@ public class TestRouterAdminCLI {
   private static final String TEST_USER = "test-user";
 
   private final ByteArrayOutputStream out = new ByteArrayOutputStream();
+  private final ByteArrayOutputStream err = new ByteArrayOutputStream();
   private static final PrintStream OLD_OUT = System.out;
+  private static final PrintStream OLD_ERR = System.err;
 
   @BeforeClass
   public static void globalSetUp() throws Exception {
@@ -102,8 +104,9 @@ public class TestRouterAdminCLI {
 
   @After
   public void tearDown() {
-    // set back system out
+    // set back system out/err
     System.setOut(OLD_OUT);
+    System.setErr(OLD_ERR);
   }
 
   @Test
@@ -462,6 +465,45 @@ public class TestRouterAdminCLI {
     assertEquals(-1, ToolRunner.run(admin, argv));
   }
 
+  @Test
+  public void testNameserviceManager() throws Exception {
+    // Disable a name service and check if it's disabled
+    assertEquals(0, ToolRunner.run(admin,
+        new String[] {"-nameservice", "disable", "ns0"}));
+
+    stateStore.loadCache(DisabledNameserviceStoreImpl.class, true);
+    System.setOut(new PrintStream(out));
+    assertEquals(0, ToolRunner.run(admin,
+        new String[] {"-getDisabledNameservices"}));
+    assertTrue("ns0 should be reported: " + out,
+        out.toString().contains("ns0"));
+
+    // Enable a name service and check if it's there
+    assertEquals(0, ToolRunner.run(admin,
+        new String[] {"-nameservice", "enable", "ns0"}));
+
+    out.reset();
+    stateStore.loadCache(DisabledNameserviceStoreImpl.class, true);
+    assertEquals(0, ToolRunner.run(admin,
+        new String[] {"-getDisabledNameservices"}));
+    assertFalse("ns0 should not be reported: " + out,
+        out.toString().contains("ns0"));
+
+    // Wrong commands
+    System.setErr(new PrintStream(err));
+    assertEquals(-1, ToolRunner.run(admin,
+        new String[] {"-nameservice", "enable"}));
+    String msg = "Not enough parameters specificed for cmd -nameservice";
+    assertTrue("Got error: " + err.toString(),
+        err.toString().startsWith(msg));
+
+    err.reset();
+    assertEquals(-1, ToolRunner.run(admin,
+        new String[] {"-nameservice", "wrong", "ns0"}));
+    assertTrue("Got error: " + err.toString(),
+        err.toString().startsWith("nameservice: Unknown command: wrong"));
+  }
+
   /**
    * Wait for the Router transforming to expected state.
    * @param expectedState Expected Router state.

+ 23 - 4
hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/store/driver/TestStateStoreDriverBase.java

@@ -41,6 +41,7 @@ import org.apache.hadoop.hdfs.server.federation.router.RouterServiceState;
 import org.apache.hadoop.hdfs.server.federation.store.FederationStateStoreTestUtils;
 import org.apache.hadoop.hdfs.server.federation.store.StateStoreService;
 import org.apache.hadoop.hdfs.server.federation.store.records.BaseRecord;
+import org.apache.hadoop.hdfs.server.federation.store.records.DisabledNameservice;
 import org.apache.hadoop.hdfs.server.federation.store.records.MembershipState;
 import org.apache.hadoop.hdfs.server.federation.store.records.MountTable;
 import org.apache.hadoop.hdfs.server.federation.store.records.Query;
@@ -139,6 +140,11 @@ public class TestStateStoreDriverBase {
       StateStoreVersion version = generateFakeRecord(StateStoreVersion.class);
       routerState.setStateStoreVersion(version);
       return (T) routerState;
+    } else if (recordClass == DisabledNameservice.class) {
+      return (T) DisabledNameservice.newInstance(generateRandomString());
+    } else if (recordClass == StateStoreVersion.class) {
+      return (T) StateStoreVersion.newInstance(
+          generateRandomLong(), generateRandomLong());
     }
 
     return null;
@@ -186,6 +192,8 @@ public class TestStateStoreDriverBase {
   public static void removeAll(StateStoreDriver driver) throws IOException {
     driver.removeAll(MembershipState.class);
     driver.removeAll(MountTable.class);
+    driver.removeAll(RouterState.class);
+    driver.removeAll(DisabledNameservice.class);
   }
 
   public <T extends BaseRecord> void testInsert(
@@ -290,7 +298,7 @@ public class TestStateStoreDriverBase {
 
     // Verify no update occurred, all original records are unchanged
     QueryResult<T> newRecords = driver.get(clazz);
-    assertTrue(newRecords.getRecords().size() == 10);
+    assertEquals(10, newRecords.getRecords().size());
     assertEquals("A single entry was improperly updated in the store", 10,
         countMatchingEntries(records.getRecords(), newRecords.getRecords()));
 
@@ -300,9 +308,12 @@ public class TestStateStoreDriverBase {
     // Verify that one entry no longer matches the original set
     newRecords = driver.get(clazz);
     assertEquals(10, newRecords.getRecords().size());
-    assertEquals(
-        "Record of type " + clazz + " not updated in the store", 9,
-        countMatchingEntries(records.getRecords(), newRecords.getRecords()));
+    T record = records.getRecords().get(0);
+    if (record.hasOtherFields()) {
+      assertEquals(
+          "Record of type " + clazz + " not updated in the store", 9,
+          countMatchingEntries(records.getRecords(), newRecords.getRecords()));
+    }
   }
 
   private int countMatchingEntries(
@@ -379,6 +390,8 @@ public class TestStateStoreDriverBase {
       throws IllegalArgumentException, IllegalAccessException, IOException {
     testInsert(driver, MembershipState.class);
     testInsert(driver, MountTable.class);
+    testInsert(driver, RouterState.class);
+    testInsert(driver, DisabledNameservice.class);
   }
 
   public void testPut(StateStoreDriver driver)
@@ -386,18 +399,24 @@ public class TestStateStoreDriverBase {
       IOException, SecurityException {
     testPut(driver, MembershipState.class);
     testPut(driver, MountTable.class);
+    testPut(driver, RouterState.class);
+    testPut(driver, DisabledNameservice.class);
   }
 
   public void testRemove(StateStoreDriver driver)
       throws IllegalArgumentException, IllegalAccessException, IOException {
     testRemove(driver, MembershipState.class);
     testRemove(driver, MountTable.class);
+    testRemove(driver, RouterState.class);
+    testRemove(driver, DisabledNameservice.class);
   }
 
   public void testFetchErrors(StateStoreDriver driver)
       throws IllegalArgumentException, IllegalAccessException, IOException {
     testFetchErrors(driver, MembershipState.class);
     testFetchErrors(driver, MountTable.class);
+    testFetchErrors(driver, RouterState.class);
+    testFetchErrors(driver, DisabledNameservice.class);
   }
 
   public void testMetrics(StateStoreDriver driver)