001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hdfs.server.namenode; 019 020import com.google.common.annotations.VisibleForTesting; 021import com.google.common.base.Joiner; 022import com.google.common.base.Preconditions; 023import com.google.common.collect.Lists; 024import org.apache.hadoop.HadoopIllegalArgumentException; 025import org.apache.hadoop.classification.InterfaceAudience; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.fs.FileSystem; 028import org.apache.hadoop.fs.Trash; 029import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState; 030import org.apache.hadoop.ha.HAServiceProtocol.StateChangeRequestInfo; 031import org.apache.hadoop.ha.HAServiceStatus; 032import org.apache.hadoop.ha.HealthCheckFailedException; 033import org.apache.hadoop.ha.ServiceFailedException; 034import org.apache.hadoop.hdfs.DFSConfigKeys; 035import org.apache.hadoop.hdfs.DFSUtil; 036import org.apache.hadoop.hdfs.HAUtil; 037import org.apache.hadoop.hdfs.HdfsConfiguration; 038import org.apache.hadoop.hdfs.protocol.ClientProtocol; 039import org.apache.hadoop.hdfs.protocol.HdfsConstants; 040import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NamenodeRole; 041import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.RollingUpgradeStartupOption; 042import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.StartupOption; 043import org.apache.hadoop.hdfs.server.namenode.ha.ActiveState; 044import org.apache.hadoop.hdfs.server.namenode.ha.BootstrapStandby; 045import org.apache.hadoop.hdfs.server.namenode.ha.HAContext; 046import org.apache.hadoop.hdfs.server.namenode.ha.HAState; 047import org.apache.hadoop.hdfs.server.namenode.ha.StandbyState; 048import org.apache.hadoop.hdfs.server.namenode.metrics.NameNodeMetrics; 049import org.apache.hadoop.hdfs.server.namenode.startupprogress.StartupProgress; 050import org.apache.hadoop.hdfs.server.namenode.startupprogress.StartupProgressMetrics; 051import org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol; 052import org.apache.hadoop.hdfs.server.protocol.JournalProtocol; 053import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocol; 054import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocols; 055import org.apache.hadoop.hdfs.server.protocol.NamenodeRegistration; 056import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo; 057import org.apache.hadoop.ipc.RefreshCallQueueProtocol; 058import org.apache.hadoop.ipc.Server; 059import org.apache.hadoop.ipc.StandbyException; 060import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; 061import org.apache.hadoop.metrics2.util.MBeans; 062import org.apache.hadoop.net.NetUtils; 063import org.apache.hadoop.security.AccessControlException; 064import org.apache.hadoop.security.RefreshUserMappingsProtocol; 065import org.apache.hadoop.security.SecurityUtil; 066import org.apache.hadoop.security.UserGroupInformation; 067import org.apache.hadoop.security.authorize.RefreshAuthorizationPolicyProtocol; 068import org.apache.hadoop.tools.GetUserMappingsProtocol; 069import org.apache.hadoop.tracing.SpanReceiverHost; 070import org.apache.hadoop.tracing.TraceAdminProtocol; 071import org.apache.hadoop.util.ExitUtil.ExitException; 072import org.apache.hadoop.util.GenericOptionsParser; 073import org.apache.hadoop.util.JvmPauseMonitor; 074import org.apache.hadoop.util.ServicePlugin; 075import org.apache.hadoop.util.StringUtils; 076import org.apache.log4j.LogManager; 077import org.slf4j.Logger; 078import org.slf4j.LoggerFactory; 079 080import javax.management.ObjectName; 081 082import java.io.IOException; 083import java.io.PrintStream; 084import java.net.InetSocketAddress; 085import java.net.URI; 086import java.security.PrivilegedExceptionAction; 087import java.util.ArrayList; 088import java.util.Arrays; 089import java.util.Collection; 090import java.util.List; 091import java.util.concurrent.atomic.AtomicBoolean; 092 093import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_DEFAULT_NAME_KEY; 094import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_DEFAULT; 095import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_KEY; 096import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_HA_AUTO_FAILOVER_ENABLED_DEFAULT; 097import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_HA_AUTO_FAILOVER_ENABLED_KEY; 098import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_HA_FENCE_METHODS_KEY; 099import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_HA_NAMENODE_ID_KEY; 100import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_HA_ZKFC_PORT_KEY; 101import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_METRICS_PERCENTILES_INTERVALS_KEY; 102import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_BACKUP_ADDRESS_KEY; 103import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_BACKUP_HTTP_ADDRESS_KEY; 104import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_BACKUP_SERVICE_RPC_ADDRESS_KEY; 105import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_CHECKPOINT_DIR_KEY; 106import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_CHECKPOINT_EDITS_DIR_KEY; 107import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_EDITS_DIR_KEY; 108import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTPS_ADDRESS_KEY; 109import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTPS_BIND_HOST_KEY; 110import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTP_ADDRESS_DEFAULT; 111import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTP_ADDRESS_KEY; 112import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTP_BIND_HOST_KEY; 113import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_KERBEROS_INTERNAL_SPNEGO_PRINCIPAL_KEY; 114import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_KERBEROS_PRINCIPAL_KEY; 115import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_KEYTAB_FILE_KEY; 116import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_NAME_DIR_KEY; 117import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_PLUGINS_KEY; 118import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY; 119import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_RPC_BIND_HOST_KEY; 120import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SECONDARY_HTTPS_ADDRESS_KEY; 121import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SECONDARY_HTTP_ADDRESS_KEY; 122import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY; 123import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SERVICE_RPC_BIND_HOST_KEY; 124import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SHARED_EDITS_DIR_KEY; 125import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_STARTUP_KEY; 126import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SUPPORT_ALLOW_FORMAT_DEFAULT; 127import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SUPPORT_ALLOW_FORMAT_KEY; 128import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMESERVICE_ID; 129import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_SECONDARY_NAMENODE_KEYTAB_FILE_KEY; 130import static org.apache.hadoop.hdfs.DFSConfigKeys.HADOOP_USER_GROUP_METRICS_PERCENTILES_INTERVALS; 131import static org.apache.hadoop.util.ExitUtil.terminate; 132import static org.apache.hadoop.util.ToolRunner.confirmPrompt; 133 134/********************************************************** 135 * NameNode serves as both directory namespace manager and 136 * "inode table" for the Hadoop DFS. There is a single NameNode 137 * running in any DFS deployment. (Well, except when there 138 * is a second backup/failover NameNode, or when using federated NameNodes.) 139 * 140 * The NameNode controls two critical tables: 141 * 1) filename->blocksequence (namespace) 142 * 2) block->machinelist ("inodes") 143 * 144 * The first table is stored on disk and is very precious. 145 * The second table is rebuilt every time the NameNode comes up. 146 * 147 * 'NameNode' refers to both this class as well as the 'NameNode server'. 148 * The 'FSNamesystem' class actually performs most of the filesystem 149 * management. The majority of the 'NameNode' class itself is concerned 150 * with exposing the IPC interface and the HTTP server to the outside world, 151 * plus some configuration management. 152 * 153 * NameNode implements the 154 * {@link org.apache.hadoop.hdfs.protocol.ClientProtocol} interface, which 155 * allows clients to ask for DFS services. 156 * {@link org.apache.hadoop.hdfs.protocol.ClientProtocol} is not designed for 157 * direct use by authors of DFS client code. End-users should instead use the 158 * {@link org.apache.hadoop.fs.FileSystem} class. 159 * 160 * NameNode also implements the 161 * {@link org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol} interface, 162 * used by DataNodes that actually store DFS data blocks. These 163 * methods are invoked repeatedly and automatically by all the 164 * DataNodes in a DFS deployment. 165 * 166 * NameNode also implements the 167 * {@link org.apache.hadoop.hdfs.server.protocol.NamenodeProtocol} interface, 168 * used by secondary namenodes or rebalancing processes to get partial 169 * NameNode state, for example partial blocksMap etc. 170 **********************************************************/ 171@InterfaceAudience.Private 172public class NameNode implements NameNodeStatusMXBean { 173 static{ 174 HdfsConfiguration.init(); 175 } 176 177 /** 178 * Categories of operations supported by the namenode. 179 */ 180 public static enum OperationCategory { 181 /** Operations that are state agnostic */ 182 UNCHECKED, 183 /** Read operation that does not change the namespace state */ 184 READ, 185 /** Write operation that changes the namespace state */ 186 WRITE, 187 /** Operations related to checkpointing */ 188 CHECKPOINT, 189 /** Operations related to {@link JournalProtocol} */ 190 JOURNAL 191 } 192 193 /** 194 * HDFS configuration can have three types of parameters: 195 * <ol> 196 * <li>Parameters that are common for all the name services in the cluster.</li> 197 * <li>Parameters that are specific to a name service. These keys are suffixed 198 * with nameserviceId in the configuration. For example, 199 * "dfs.namenode.rpc-address.nameservice1".</li> 200 * <li>Parameters that are specific to a single name node. These keys are suffixed 201 * with nameserviceId and namenodeId in the configuration. for example, 202 * "dfs.namenode.rpc-address.nameservice1.namenode1"</li> 203 * </ol> 204 * 205 * In the latter cases, operators may specify the configuration without 206 * any suffix, with a nameservice suffix, or with a nameservice and namenode 207 * suffix. The more specific suffix will take precedence. 208 * 209 * These keys are specific to a given namenode, and thus may be configured 210 * globally, for a nameservice, or for a specific namenode within a nameservice. 211 */ 212 public static final String[] NAMENODE_SPECIFIC_KEYS = { 213 DFS_NAMENODE_RPC_ADDRESS_KEY, 214 DFS_NAMENODE_RPC_BIND_HOST_KEY, 215 DFS_NAMENODE_NAME_DIR_KEY, 216 DFS_NAMENODE_EDITS_DIR_KEY, 217 DFS_NAMENODE_SHARED_EDITS_DIR_KEY, 218 DFS_NAMENODE_CHECKPOINT_DIR_KEY, 219 DFS_NAMENODE_CHECKPOINT_EDITS_DIR_KEY, 220 DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, 221 DFS_NAMENODE_SERVICE_RPC_BIND_HOST_KEY, 222 DFS_NAMENODE_HTTP_ADDRESS_KEY, 223 DFS_NAMENODE_HTTPS_ADDRESS_KEY, 224 DFS_NAMENODE_HTTP_BIND_HOST_KEY, 225 DFS_NAMENODE_HTTPS_BIND_HOST_KEY, 226 DFS_NAMENODE_KEYTAB_FILE_KEY, 227 DFS_NAMENODE_SECONDARY_HTTP_ADDRESS_KEY, 228 DFS_NAMENODE_SECONDARY_HTTPS_ADDRESS_KEY, 229 DFS_SECONDARY_NAMENODE_KEYTAB_FILE_KEY, 230 DFS_NAMENODE_BACKUP_ADDRESS_KEY, 231 DFS_NAMENODE_BACKUP_HTTP_ADDRESS_KEY, 232 DFS_NAMENODE_BACKUP_SERVICE_RPC_ADDRESS_KEY, 233 DFS_NAMENODE_KERBEROS_PRINCIPAL_KEY, 234 DFS_NAMENODE_KERBEROS_INTERNAL_SPNEGO_PRINCIPAL_KEY, 235 DFS_HA_FENCE_METHODS_KEY, 236 DFS_HA_ZKFC_PORT_KEY, 237 DFS_HA_FENCE_METHODS_KEY 238 }; 239 240 /** 241 * @see #NAMENODE_SPECIFIC_KEYS 242 * These keys are specific to a nameservice, but may not be overridden 243 * for a specific namenode. 244 */ 245 public static final String[] NAMESERVICE_SPECIFIC_KEYS = { 246 DFS_HA_AUTO_FAILOVER_ENABLED_KEY 247 }; 248 249 private static final String USAGE = "Usage: java NameNode [" 250 + StartupOption.BACKUP.getName() + "] | \n\t[" 251 + StartupOption.CHECKPOINT.getName() + "] | \n\t[" 252 + StartupOption.FORMAT.getName() + " [" 253 + StartupOption.CLUSTERID.getName() + " cid ] [" 254 + StartupOption.FORCE.getName() + "] [" 255 + StartupOption.NONINTERACTIVE.getName() + "] ] | \n\t[" 256 + StartupOption.UPGRADE.getName() + 257 " [" + StartupOption.CLUSTERID.getName() + " cid]" + 258 " [" + StartupOption.RENAMERESERVED.getName() + "<k-v pairs>] ] | \n\t[" 259 + StartupOption.UPGRADEONLY.getName() + 260 " [" + StartupOption.CLUSTERID.getName() + " cid]" + 261 " [" + StartupOption.RENAMERESERVED.getName() + "<k-v pairs>] ] | \n\t[" 262 + StartupOption.ROLLBACK.getName() + "] | \n\t[" 263 + StartupOption.ROLLINGUPGRADE.getName() + " " 264 + RollingUpgradeStartupOption.getAllOptionString() + " ] | \n\t[" 265 + StartupOption.FINALIZE.getName() + "] | \n\t[" 266 + StartupOption.IMPORT.getName() + "] | \n\t[" 267 + StartupOption.INITIALIZESHAREDEDITS.getName() + "] | \n\t[" 268 + StartupOption.BOOTSTRAPSTANDBY.getName() + "] | \n\t[" 269 + StartupOption.RECOVER.getName() + " [ " 270 + StartupOption.FORCE.getName() + "] ] | \n\t[" 271 + StartupOption.METADATAVERSION.getName() + " ] " 272 + " ]"; 273 274 275 public long getProtocolVersion(String protocol, 276 long clientVersion) throws IOException { 277 if (protocol.equals(ClientProtocol.class.getName())) { 278 return ClientProtocol.versionID; 279 } else if (protocol.equals(DatanodeProtocol.class.getName())){ 280 return DatanodeProtocol.versionID; 281 } else if (protocol.equals(NamenodeProtocol.class.getName())){ 282 return NamenodeProtocol.versionID; 283 } else if (protocol.equals(RefreshAuthorizationPolicyProtocol.class.getName())){ 284 return RefreshAuthorizationPolicyProtocol.versionID; 285 } else if (protocol.equals(RefreshUserMappingsProtocol.class.getName())){ 286 return RefreshUserMappingsProtocol.versionID; 287 } else if (protocol.equals(RefreshCallQueueProtocol.class.getName())) { 288 return RefreshCallQueueProtocol.versionID; 289 } else if (protocol.equals(GetUserMappingsProtocol.class.getName())){ 290 return GetUserMappingsProtocol.versionID; 291 } else if (protocol.equals(TraceAdminProtocol.class.getName())){ 292 return TraceAdminProtocol.versionID; 293 } else { 294 throw new IOException("Unknown protocol to name node: " + protocol); 295 } 296 } 297 298 public static final int DEFAULT_PORT = 8020; 299 public static final Logger LOG = 300 LoggerFactory.getLogger(NameNode.class.getName()); 301 public static final Logger stateChangeLog = 302 LoggerFactory.getLogger("org.apache.hadoop.hdfs.StateChange"); 303 public static final Logger blockStateChangeLog = 304 LoggerFactory.getLogger("BlockStateChange"); 305 public static final HAState ACTIVE_STATE = new ActiveState(); 306 public static final HAState STANDBY_STATE = new StandbyState(); 307 308 protected FSNamesystem namesystem; 309 protected final Configuration conf; 310 protected final NamenodeRole role; 311 private volatile HAState state; 312 private final boolean haEnabled; 313 private final HAContext haContext; 314 protected final boolean allowStaleStandbyReads; 315 private AtomicBoolean started = new AtomicBoolean(false); 316 317 318 /** httpServer */ 319 protected NameNodeHttpServer httpServer; 320 private Thread emptier; 321 /** only used for testing purposes */ 322 protected boolean stopRequested = false; 323 /** Registration information of this name-node */ 324 protected NamenodeRegistration nodeRegistration; 325 /** Activated plug-ins. */ 326 private List<ServicePlugin> plugins; 327 328 private NameNodeRpcServer rpcServer; 329 330 private JvmPauseMonitor pauseMonitor; 331 private ObjectName nameNodeStatusBeanName; 332 SpanReceiverHost spanReceiverHost; 333 /** 334 * The namenode address that clients will use to access this namenode 335 * or the name service. For HA configurations using logical URI, it 336 * will be the logical address. 337 */ 338 private String clientNamenodeAddress; 339 340 /** Format a new filesystem. Destroys any filesystem that may already 341 * exist at this location. **/ 342 public static void format(Configuration conf) throws IOException { 343 format(conf, true, true); 344 } 345 346 static NameNodeMetrics metrics; 347 private static final StartupProgress startupProgress = new StartupProgress(); 348 /** Return the {@link FSNamesystem} object. 349 * @return {@link FSNamesystem} object. 350 */ 351 public FSNamesystem getNamesystem() { 352 return namesystem; 353 } 354 355 public NamenodeProtocols getRpcServer() { 356 return rpcServer; 357 } 358 359 static void initMetrics(Configuration conf, NamenodeRole role) { 360 metrics = NameNodeMetrics.create(conf, role); 361 } 362 363 public static NameNodeMetrics getNameNodeMetrics() { 364 return metrics; 365 } 366 367 /** 368 * Returns object used for reporting namenode startup progress. 369 * 370 * @return StartupProgress for reporting namenode startup progress 371 */ 372 public static StartupProgress getStartupProgress() { 373 return startupProgress; 374 } 375 376 /** 377 * Return the service name of the issued delegation token. 378 * 379 * @return The name service id in HA-mode, or the rpc address in non-HA mode 380 */ 381 public String getTokenServiceName() { 382 return getClientNamenodeAddress(); 383 } 384 385 /** 386 * Set the namenode address that will be used by clients to access this 387 * namenode or name service. This needs to be called before the config 388 * is overriden. 389 */ 390 public void setClientNamenodeAddress(Configuration conf) { 391 String nnAddr = conf.get(FS_DEFAULT_NAME_KEY); 392 if (nnAddr == null) { 393 // default fs is not set. 394 clientNamenodeAddress = null; 395 return; 396 } 397 398 LOG.info("{} is {}", FS_DEFAULT_NAME_KEY, nnAddr); 399 URI nnUri = URI.create(nnAddr); 400 401 String nnHost = nnUri.getHost(); 402 if (nnHost == null) { 403 clientNamenodeAddress = null; 404 return; 405 } 406 407 if (DFSUtil.getNameServiceIds(conf).contains(nnHost)) { 408 // host name is logical 409 clientNamenodeAddress = nnHost; 410 } else if (nnUri.getPort() > 0) { 411 // physical address with a valid port 412 clientNamenodeAddress = nnUri.getAuthority(); 413 } else { 414 // the port is missing or 0. Figure out real bind address later. 415 clientNamenodeAddress = null; 416 return; 417 } 418 LOG.info("Clients are to use {} to access" 419 + " this namenode/service.", clientNamenodeAddress ); 420 } 421 422 /** 423 * Get the namenode address to be used by clients. 424 * @return nn address 425 */ 426 public String getClientNamenodeAddress() { 427 return clientNamenodeAddress; 428 } 429 430 public static InetSocketAddress getAddress(String address) { 431 return NetUtils.createSocketAddr(address, DEFAULT_PORT); 432 } 433 434 /** 435 * Set the configuration property for the service rpc address 436 * to address 437 */ 438 public static void setServiceAddress(Configuration conf, 439 String address) { 440 LOG.info("Setting ADDRESS {}", address); 441 conf.set(DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, address); 442 } 443 444 /** 445 * Fetches the address for services to use when connecting to namenode 446 * based on the value of fallback returns null if the special 447 * address is not specified or returns the default namenode address 448 * to be used by both clients and services. 449 * Services here are datanodes, backup node, any non client connection 450 */ 451 public static InetSocketAddress getServiceAddress(Configuration conf, 452 boolean fallback) { 453 String addr = conf.getTrimmed(DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY); 454 if (addr == null || addr.isEmpty()) { 455 return fallback ? getAddress(conf) : null; 456 } 457 return getAddress(addr); 458 } 459 460 public static InetSocketAddress getAddress(Configuration conf) { 461 URI filesystemURI = FileSystem.getDefaultUri(conf); 462 return getAddress(filesystemURI); 463 } 464 465 466 /** 467 * @return address of file system 468 */ 469 public static InetSocketAddress getAddress(URI filesystemURI) { 470 String authority = filesystemURI.getAuthority(); 471 if (authority == null) { 472 throw new IllegalArgumentException(String.format( 473 "Invalid URI for NameNode address (check %s): %s has no authority.", 474 FileSystem.FS_DEFAULT_NAME_KEY, filesystemURI.toString())); 475 } 476 if (!HdfsConstants.HDFS_URI_SCHEME.equalsIgnoreCase( 477 filesystemURI.getScheme())) { 478 throw new IllegalArgumentException(String.format( 479 "Invalid URI for NameNode address (check %s): %s is not of scheme '%s'.", 480 FileSystem.FS_DEFAULT_NAME_KEY, filesystemURI.toString(), 481 HdfsConstants.HDFS_URI_SCHEME)); 482 } 483 return getAddress(authority); 484 } 485 486 public static URI getUri(InetSocketAddress namenode) { 487 int port = namenode.getPort(); 488 String portString = port == DEFAULT_PORT ? "" : (":"+port); 489 return URI.create(HdfsConstants.HDFS_URI_SCHEME + "://" 490 + namenode.getHostName()+portString); 491 } 492 493 // 494 // Common NameNode methods implementation for the active name-node role. 495 // 496 public NamenodeRole getRole() { 497 return role; 498 } 499 500 boolean isRole(NamenodeRole that) { 501 return role.equals(that); 502 } 503 504 /** 505 * Given a configuration get the address of the service rpc server 506 * If the service rpc is not configured returns null 507 */ 508 protected InetSocketAddress getServiceRpcServerAddress(Configuration conf) { 509 return NameNode.getServiceAddress(conf, false); 510 } 511 512 protected InetSocketAddress getRpcServerAddress(Configuration conf) { 513 return getAddress(conf); 514 } 515 516 /** Given a configuration get the bind host of the service rpc server 517 * If the bind host is not configured returns null. 518 */ 519 protected String getServiceRpcServerBindHost(Configuration conf) { 520 String addr = conf.getTrimmed(DFS_NAMENODE_SERVICE_RPC_BIND_HOST_KEY); 521 if (addr == null || addr.isEmpty()) { 522 return null; 523 } 524 return addr; 525 } 526 527 /** Given a configuration get the bind host of the client rpc server 528 * If the bind host is not configured returns null. 529 */ 530 protected String getRpcServerBindHost(Configuration conf) { 531 String addr = conf.getTrimmed(DFS_NAMENODE_RPC_BIND_HOST_KEY); 532 if (addr == null || addr.isEmpty()) { 533 return null; 534 } 535 return addr; 536 } 537 538 /** 539 * Modifies the configuration passed to contain the service rpc address setting 540 */ 541 protected void setRpcServiceServerAddress(Configuration conf, 542 InetSocketAddress serviceRPCAddress) { 543 setServiceAddress(conf, NetUtils.getHostPortString(serviceRPCAddress)); 544 } 545 546 protected void setRpcServerAddress(Configuration conf, 547 InetSocketAddress rpcAddress) { 548 FileSystem.setDefaultUri(conf, getUri(rpcAddress)); 549 } 550 551 protected InetSocketAddress getHttpServerAddress(Configuration conf) { 552 return getHttpAddress(conf); 553 } 554 555 /** 556 * HTTP server address for binding the endpoint. This method is 557 * for use by the NameNode and its derivatives. It may return 558 * a different address than the one that should be used by clients to 559 * connect to the NameNode. See 560 * {@link DFSConfigKeys#DFS_NAMENODE_HTTP_BIND_HOST_KEY} 561 * 562 * @param conf 563 * @return 564 */ 565 protected InetSocketAddress getHttpServerBindAddress(Configuration conf) { 566 InetSocketAddress bindAddress = getHttpServerAddress(conf); 567 568 // If DFS_NAMENODE_HTTP_BIND_HOST_KEY exists then it overrides the 569 // host name portion of DFS_NAMENODE_HTTP_ADDRESS_KEY. 570 final String bindHost = conf.getTrimmed(DFS_NAMENODE_HTTP_BIND_HOST_KEY); 571 if (bindHost != null && !bindHost.isEmpty()) { 572 bindAddress = new InetSocketAddress(bindHost, bindAddress.getPort()); 573 } 574 575 return bindAddress; 576 } 577 578 /** @return the NameNode HTTP address. */ 579 public static InetSocketAddress getHttpAddress(Configuration conf) { 580 return NetUtils.createSocketAddr( 581 conf.getTrimmed(DFS_NAMENODE_HTTP_ADDRESS_KEY, DFS_NAMENODE_HTTP_ADDRESS_DEFAULT)); 582 } 583 584 protected void loadNamesystem(Configuration conf) throws IOException { 585 this.namesystem = FSNamesystem.loadFromDisk(conf); 586 } 587 588 NamenodeRegistration getRegistration() { 589 return nodeRegistration; 590 } 591 592 NamenodeRegistration setRegistration() { 593 nodeRegistration = new NamenodeRegistration( 594 NetUtils.getHostPortString(rpcServer.getRpcAddress()), 595 NetUtils.getHostPortString(getHttpAddress()), 596 getFSImage().getStorage(), getRole()); 597 return nodeRegistration; 598 } 599 600 /* optimize ugi lookup for RPC operations to avoid a trip through 601 * UGI.getCurrentUser which is synch'ed 602 */ 603 public static UserGroupInformation getRemoteUser() throws IOException { 604 UserGroupInformation ugi = Server.getRemoteUser(); 605 return (ugi != null) ? ugi : UserGroupInformation.getCurrentUser(); 606 } 607 608 609 /** 610 * Login as the configured user for the NameNode. 611 */ 612 void loginAsNameNodeUser(Configuration conf) throws IOException { 613 InetSocketAddress socAddr = getRpcServerAddress(conf); 614 SecurityUtil.login(conf, DFS_NAMENODE_KEYTAB_FILE_KEY, 615 DFS_NAMENODE_KERBEROS_PRINCIPAL_KEY, socAddr.getHostName()); 616 } 617 618 /** 619 * Initialize name-node. 620 * 621 * @param conf the configuration 622 */ 623 protected void initialize(Configuration conf) throws IOException { 624 if (conf.get(HADOOP_USER_GROUP_METRICS_PERCENTILES_INTERVALS) == null) { 625 String intervals = conf.get(DFS_METRICS_PERCENTILES_INTERVALS_KEY); 626 if (intervals != null) { 627 conf.set(HADOOP_USER_GROUP_METRICS_PERCENTILES_INTERVALS, 628 intervals); 629 } 630 } 631 632 UserGroupInformation.setConfiguration(conf); 633 loginAsNameNodeUser(conf); 634 635 NameNode.initMetrics(conf, this.getRole()); 636 StartupProgressMetrics.register(startupProgress); 637 638 if (NamenodeRole.NAMENODE == role) { 639 startHttpServer(conf); 640 } 641 642 this.spanReceiverHost = 643 SpanReceiverHost.get(conf, DFSConfigKeys.DFS_SERVER_HTRACE_PREFIX); 644 645 loadNamesystem(conf); 646 647 rpcServer = createRpcServer(conf); 648 if (clientNamenodeAddress == null) { 649 // This is expected for MiniDFSCluster. Set it now using 650 // the RPC server's bind address. 651 clientNamenodeAddress = 652 NetUtils.getHostPortString(rpcServer.getRpcAddress()); 653 LOG.info("Clients are to use " + clientNamenodeAddress + " to access" 654 + " this namenode/service."); 655 } 656 if (NamenodeRole.NAMENODE == role) { 657 httpServer.setNameNodeAddress(getNameNodeAddress()); 658 httpServer.setFSImage(getFSImage()); 659 } 660 661 pauseMonitor = new JvmPauseMonitor(conf); 662 pauseMonitor.start(); 663 metrics.getJvmMetrics().setPauseMonitor(pauseMonitor); 664 665 startCommonServices(conf); 666 } 667 668 /** 669 * Create the RPC server implementation. Used as an extension point for the 670 * BackupNode. 671 */ 672 protected NameNodeRpcServer createRpcServer(Configuration conf) 673 throws IOException { 674 return new NameNodeRpcServer(conf, this); 675 } 676 677 /** Start the services common to active and standby states */ 678 private void startCommonServices(Configuration conf) throws IOException { 679 namesystem.startCommonServices(conf, haContext); 680 registerNNSMXBean(); 681 if (NamenodeRole.NAMENODE != role) { 682 startHttpServer(conf); 683 httpServer.setNameNodeAddress(getNameNodeAddress()); 684 httpServer.setFSImage(getFSImage()); 685 } 686 rpcServer.start(); 687 try { 688 plugins = conf.getInstances(DFS_NAMENODE_PLUGINS_KEY, 689 ServicePlugin.class); 690 } catch (RuntimeException e) { 691 String pluginsValue = conf.get(DFS_NAMENODE_PLUGINS_KEY); 692 LOG.error("Unable to load NameNode plugins. Specified list of plugins: " + 693 pluginsValue, e); 694 throw e; 695 } 696 for (ServicePlugin p: plugins) { 697 try { 698 p.start(this); 699 } catch (Throwable t) { 700 LOG.warn("ServicePlugin " + p + " could not be started", t); 701 } 702 } 703 LOG.info(getRole() + " RPC up at: " + rpcServer.getRpcAddress()); 704 if (rpcServer.getServiceRpcAddress() != null) { 705 LOG.info(getRole() + " service RPC up at: " 706 + rpcServer.getServiceRpcAddress()); 707 } 708 } 709 710 private void stopCommonServices() { 711 if(rpcServer != null) rpcServer.stop(); 712 if(namesystem != null) namesystem.close(); 713 if (pauseMonitor != null) pauseMonitor.stop(); 714 if (plugins != null) { 715 for (ServicePlugin p : plugins) { 716 try { 717 p.stop(); 718 } catch (Throwable t) { 719 LOG.warn("ServicePlugin " + p + " could not be stopped", t); 720 } 721 } 722 } 723 stopHttpServer(); 724 } 725 726 private void startTrashEmptier(final Configuration conf) throws IOException { 727 long trashInterval = 728 conf.getLong(FS_TRASH_INTERVAL_KEY, FS_TRASH_INTERVAL_DEFAULT); 729 if (trashInterval == 0) { 730 return; 731 } else if (trashInterval < 0) { 732 throw new IOException("Cannot start trash emptier with negative interval." 733 + " Set " + FS_TRASH_INTERVAL_KEY + " to a positive value."); 734 } 735 736 // This may be called from the transitionToActive code path, in which 737 // case the current user is the administrator, not the NN. The trash 738 // emptier needs to run as the NN. See HDFS-3972. 739 FileSystem fs = SecurityUtil.doAsLoginUser( 740 new PrivilegedExceptionAction<FileSystem>() { 741 @Override 742 public FileSystem run() throws IOException { 743 return FileSystem.get(conf); 744 } 745 }); 746 this.emptier = new Thread(new Trash(fs, conf).getEmptier(), "Trash Emptier"); 747 this.emptier.setDaemon(true); 748 this.emptier.start(); 749 } 750 751 private void stopTrashEmptier() { 752 if (this.emptier != null) { 753 emptier.interrupt(); 754 emptier = null; 755 } 756 } 757 758 private void startHttpServer(final Configuration conf) throws IOException { 759 httpServer = new NameNodeHttpServer(conf, this, getHttpServerBindAddress(conf)); 760 httpServer.start(); 761 httpServer.setStartupProgress(startupProgress); 762 } 763 764 private void stopHttpServer() { 765 try { 766 if (httpServer != null) httpServer.stop(); 767 } catch (Exception e) { 768 LOG.error("Exception while stopping httpserver", e); 769 } 770 } 771 772 /** 773 * Start NameNode. 774 * <p> 775 * The name-node can be started with one of the following startup options: 776 * <ul> 777 * <li>{@link StartupOption#REGULAR REGULAR} - normal name node startup</li> 778 * <li>{@link StartupOption#FORMAT FORMAT} - format name node</li> 779 * <li>{@link StartupOption#BACKUP BACKUP} - start backup node</li> 780 * <li>{@link StartupOption#CHECKPOINT CHECKPOINT} - start checkpoint node</li> 781 * <li>{@link StartupOption#UPGRADE UPGRADE} - start the cluster 782 * <li>{@link StartupOption#UPGRADEONLY UPGRADEONLY} - upgrade the cluster 783 * upgrade and create a snapshot of the current file system state</li> 784 * <li>{@link StartupOption#RECOVER RECOVERY} - recover name node 785 * metadata</li> 786 * <li>{@link StartupOption#ROLLBACK ROLLBACK} - roll the 787 * cluster back to the previous state</li> 788 * <li>{@link StartupOption#FINALIZE FINALIZE} - finalize 789 * previous upgrade</li> 790 * <li>{@link StartupOption#IMPORT IMPORT} - import checkpoint</li> 791 * </ul> 792 * The option is passed via configuration field: 793 * <tt>dfs.namenode.startup</tt> 794 * 795 * The conf will be modified to reflect the actual ports on which 796 * the NameNode is up and running if the user passes the port as 797 * <code>zero</code> in the conf. 798 * 799 * @param conf confirguration 800 * @throws IOException 801 */ 802 public NameNode(Configuration conf) throws IOException { 803 this(conf, NamenodeRole.NAMENODE); 804 } 805 806 protected NameNode(Configuration conf, NamenodeRole role) 807 throws IOException { 808 this.conf = conf; 809 this.role = role; 810 setClientNamenodeAddress(conf); 811 String nsId = getNameServiceId(conf); 812 String namenodeId = HAUtil.getNameNodeId(conf, nsId); 813 this.haEnabled = HAUtil.isHAEnabled(conf, nsId); 814 state = createHAState(getStartupOption(conf)); 815 this.allowStaleStandbyReads = HAUtil.shouldAllowStandbyReads(conf); 816 this.haContext = createHAContext(); 817 try { 818 initializeGenericKeys(conf, nsId, namenodeId); 819 initialize(conf); 820 try { 821 haContext.writeLock(); 822 state.prepareToEnterState(haContext); 823 state.enterState(haContext); 824 } finally { 825 haContext.writeUnlock(); 826 } 827 } catch (IOException e) { 828 this.stop(); 829 throw e; 830 } catch (HadoopIllegalArgumentException e) { 831 this.stop(); 832 throw e; 833 } 834 this.started.set(true); 835 } 836 837 protected HAState createHAState(StartupOption startOpt) { 838 if (!haEnabled || startOpt == StartupOption.UPGRADE 839 || startOpt == StartupOption.UPGRADEONLY) { 840 return ACTIVE_STATE; 841 } else { 842 return STANDBY_STATE; 843 } 844 } 845 846 protected HAContext createHAContext() { 847 return new NameNodeHAContext(); 848 } 849 850 /** 851 * Wait for service to finish. 852 * (Normally, it runs forever.) 853 */ 854 public void join() { 855 try { 856 rpcServer.join(); 857 } catch (InterruptedException ie) { 858 LOG.info("Caught interrupted exception ", ie); 859 } 860 } 861 862 /** 863 * Stop all NameNode threads and wait for all to finish. 864 */ 865 public void stop() { 866 synchronized(this) { 867 if (stopRequested) 868 return; 869 stopRequested = true; 870 } 871 try { 872 if (state != null) { 873 state.exitState(haContext); 874 } 875 } catch (ServiceFailedException e) { 876 LOG.warn("Encountered exception while exiting state ", e); 877 } finally { 878 stopCommonServices(); 879 if (metrics != null) { 880 metrics.shutdown(); 881 } 882 if (namesystem != null) { 883 namesystem.shutdown(); 884 } 885 if (nameNodeStatusBeanName != null) { 886 MBeans.unregister(nameNodeStatusBeanName); 887 nameNodeStatusBeanName = null; 888 } 889 if (this.spanReceiverHost != null) { 890 this.spanReceiverHost.closeReceivers(); 891 } 892 } 893 } 894 895 synchronized boolean isStopRequested() { 896 return stopRequested; 897 } 898 899 /** 900 * Is the cluster currently in safe mode? 901 */ 902 public boolean isInSafeMode() { 903 return namesystem.isInSafeMode(); 904 } 905 906 /** get FSImage */ 907 @VisibleForTesting 908 public FSImage getFSImage() { 909 return namesystem.getFSImage(); 910 } 911 912 /** 913 * @return NameNode RPC address 914 */ 915 public InetSocketAddress getNameNodeAddress() { 916 return rpcServer.getRpcAddress(); 917 } 918 919 /** 920 * @return NameNode RPC address in "host:port" string form 921 */ 922 public String getNameNodeAddressHostPortString() { 923 return NetUtils.getHostPortString(rpcServer.getRpcAddress()); 924 } 925 926 /** 927 * @return NameNode service RPC address if configured, the 928 * NameNode RPC address otherwise 929 */ 930 public InetSocketAddress getServiceRpcAddress() { 931 final InetSocketAddress serviceAddr = rpcServer.getServiceRpcAddress(); 932 return serviceAddr == null ? rpcServer.getRpcAddress() : serviceAddr; 933 } 934 935 /** 936 * @return NameNode HTTP address, used by the Web UI, image transfer, 937 * and HTTP-based file system clients like Hftp and WebHDFS 938 */ 939 public InetSocketAddress getHttpAddress() { 940 return httpServer.getHttpAddress(); 941 } 942 943 /** 944 * @return NameNode HTTPS address, used by the Web UI, image transfer, 945 * and HTTP-based file system clients like Hftp and WebHDFS 946 */ 947 public InetSocketAddress getHttpsAddress() { 948 return httpServer.getHttpsAddress(); 949 } 950 951 /** 952 * Verify that configured directories exist, then 953 * Interactively confirm that formatting is desired 954 * for each existing directory and format them. 955 * 956 * @param conf configuration to use 957 * @param force if true, format regardless of whether dirs exist 958 * @return true if formatting was aborted, false otherwise 959 * @throws IOException 960 */ 961 private static boolean format(Configuration conf, boolean force, 962 boolean isInteractive) throws IOException { 963 String nsId = DFSUtil.getNamenodeNameServiceId(conf); 964 String namenodeId = HAUtil.getNameNodeId(conf, nsId); 965 initializeGenericKeys(conf, nsId, namenodeId); 966 checkAllowFormat(conf); 967 968 if (UserGroupInformation.isSecurityEnabled()) { 969 InetSocketAddress socAddr = getAddress(conf); 970 SecurityUtil.login(conf, DFS_NAMENODE_KEYTAB_FILE_KEY, 971 DFS_NAMENODE_KERBEROS_PRINCIPAL_KEY, socAddr.getHostName()); 972 } 973 974 Collection<URI> nameDirsToFormat = FSNamesystem.getNamespaceDirs(conf); 975 List<URI> sharedDirs = FSNamesystem.getSharedEditsDirs(conf); 976 List<URI> dirsToPrompt = new ArrayList<URI>(); 977 dirsToPrompt.addAll(nameDirsToFormat); 978 dirsToPrompt.addAll(sharedDirs); 979 List<URI> editDirsToFormat = 980 FSNamesystem.getNamespaceEditsDirs(conf); 981 982 // if clusterID is not provided - see if you can find the current one 983 String clusterId = StartupOption.FORMAT.getClusterId(); 984 if(clusterId == null || clusterId.equals("")) { 985 //Generate a new cluster id 986 clusterId = NNStorage.newClusterID(); 987 } 988 System.out.println("Formatting using clusterid: " + clusterId); 989 990 FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat); 991 try { 992 FSNamesystem fsn = new FSNamesystem(conf, fsImage); 993 fsImage.getEditLog().initJournalsForWrite(); 994 995 if (!fsImage.confirmFormat(force, isInteractive)) { 996 return true; // aborted 997 } 998 999 fsImage.format(fsn, clusterId); 1000 } catch (IOException ioe) { 1001 LOG.warn("Encountered exception during format: ", ioe); 1002 fsImage.close(); 1003 throw ioe; 1004 } 1005 return false; 1006 } 1007 1008 public static void checkAllowFormat(Configuration conf) throws IOException { 1009 if (!conf.getBoolean(DFS_NAMENODE_SUPPORT_ALLOW_FORMAT_KEY, 1010 DFS_NAMENODE_SUPPORT_ALLOW_FORMAT_DEFAULT)) { 1011 throw new IOException("The option " + DFS_NAMENODE_SUPPORT_ALLOW_FORMAT_KEY 1012 + " is set to false for this filesystem, so it " 1013 + "cannot be formatted. You will need to set " 1014 + DFS_NAMENODE_SUPPORT_ALLOW_FORMAT_KEY +" parameter " 1015 + "to true in order to format this filesystem"); 1016 } 1017 } 1018 1019 @VisibleForTesting 1020 public static boolean initializeSharedEdits(Configuration conf) throws IOException { 1021 return initializeSharedEdits(conf, true); 1022 } 1023 1024 @VisibleForTesting 1025 public static boolean initializeSharedEdits(Configuration conf, 1026 boolean force) throws IOException { 1027 return initializeSharedEdits(conf, force, false); 1028 } 1029 1030 /** 1031 * Clone the supplied configuration but remove the shared edits dirs. 1032 * 1033 * @param conf Supplies the original configuration. 1034 * @return Cloned configuration without the shared edit dirs. 1035 * @throws IOException on failure to generate the configuration. 1036 */ 1037 private static Configuration getConfigurationWithoutSharedEdits( 1038 Configuration conf) 1039 throws IOException { 1040 List<URI> editsDirs = FSNamesystem.getNamespaceEditsDirs(conf, false); 1041 String editsDirsString = Joiner.on(",").join(editsDirs); 1042 1043 Configuration confWithoutShared = new Configuration(conf); 1044 confWithoutShared.unset(DFSConfigKeys.DFS_NAMENODE_SHARED_EDITS_DIR_KEY); 1045 confWithoutShared.setStrings(DFSConfigKeys.DFS_NAMENODE_EDITS_DIR_KEY, 1046 editsDirsString); 1047 return confWithoutShared; 1048 } 1049 1050 /** 1051 * Format a new shared edits dir and copy in enough edit log segments so that 1052 * the standby NN can start up. 1053 * 1054 * @param conf configuration 1055 * @param force format regardless of whether or not the shared edits dir exists 1056 * @param interactive prompt the user when a dir exists 1057 * @return true if the command aborts, false otherwise 1058 */ 1059 private static boolean initializeSharedEdits(Configuration conf, 1060 boolean force, boolean interactive) throws IOException { 1061 String nsId = DFSUtil.getNamenodeNameServiceId(conf); 1062 String namenodeId = HAUtil.getNameNodeId(conf, nsId); 1063 initializeGenericKeys(conf, nsId, namenodeId); 1064 1065 if (conf.get(DFSConfigKeys.DFS_NAMENODE_SHARED_EDITS_DIR_KEY) == null) { 1066 LOG.error("No shared edits directory configured for namespace " + 1067 nsId + " namenode " + namenodeId); 1068 return false; 1069 } 1070 1071 if (UserGroupInformation.isSecurityEnabled()) { 1072 InetSocketAddress socAddr = getAddress(conf); 1073 SecurityUtil.login(conf, DFS_NAMENODE_KEYTAB_FILE_KEY, 1074 DFS_NAMENODE_KERBEROS_PRINCIPAL_KEY, socAddr.getHostName()); 1075 } 1076 1077 NNStorage existingStorage = null; 1078 FSImage sharedEditsImage = null; 1079 try { 1080 FSNamesystem fsns = 1081 FSNamesystem.loadFromDisk(getConfigurationWithoutSharedEdits(conf)); 1082 1083 existingStorage = fsns.getFSImage().getStorage(); 1084 NamespaceInfo nsInfo = existingStorage.getNamespaceInfo(); 1085 1086 List<URI> sharedEditsDirs = FSNamesystem.getSharedEditsDirs(conf); 1087 1088 sharedEditsImage = new FSImage(conf, 1089 Lists.<URI>newArrayList(), 1090 sharedEditsDirs); 1091 sharedEditsImage.getEditLog().initJournalsForWrite(); 1092 1093 if (!sharedEditsImage.confirmFormat(force, interactive)) { 1094 return true; // abort 1095 } 1096 1097 NNStorage newSharedStorage = sharedEditsImage.getStorage(); 1098 // Call Storage.format instead of FSImage.format here, since we don't 1099 // actually want to save a checkpoint - just prime the dirs with 1100 // the existing namespace info 1101 newSharedStorage.format(nsInfo); 1102 sharedEditsImage.getEditLog().formatNonFileJournals(nsInfo); 1103 1104 // Need to make sure the edit log segments are in good shape to initialize 1105 // the shared edits dir. 1106 fsns.getFSImage().getEditLog().close(); 1107 fsns.getFSImage().getEditLog().initJournalsForWrite(); 1108 fsns.getFSImage().getEditLog().recoverUnclosedStreams(); 1109 1110 copyEditLogSegmentsToSharedDir(fsns, sharedEditsDirs, newSharedStorage, 1111 conf); 1112 } catch (IOException ioe) { 1113 LOG.error("Could not initialize shared edits dir", ioe); 1114 return true; // aborted 1115 } finally { 1116 if (sharedEditsImage != null) { 1117 try { 1118 sharedEditsImage.close(); 1119 } catch (IOException ioe) { 1120 LOG.warn("Could not close sharedEditsImage", ioe); 1121 } 1122 } 1123 // Have to unlock storage explicitly for the case when we're running in a 1124 // unit test, which runs in the same JVM as NNs. 1125 if (existingStorage != null) { 1126 try { 1127 existingStorage.unlockAll(); 1128 } catch (IOException ioe) { 1129 LOG.warn("Could not unlock storage directories", ioe); 1130 return true; // aborted 1131 } 1132 } 1133 } 1134 return false; // did not abort 1135 } 1136 1137 private static void copyEditLogSegmentsToSharedDir(FSNamesystem fsns, 1138 Collection<URI> sharedEditsDirs, NNStorage newSharedStorage, 1139 Configuration conf) throws IOException { 1140 Preconditions.checkArgument(!sharedEditsDirs.isEmpty(), 1141 "No shared edits specified"); 1142 // Copy edit log segments into the new shared edits dir. 1143 List<URI> sharedEditsUris = new ArrayList<URI>(sharedEditsDirs); 1144 FSEditLog newSharedEditLog = new FSEditLog(conf, newSharedStorage, 1145 sharedEditsUris); 1146 newSharedEditLog.initJournalsForWrite(); 1147 newSharedEditLog.recoverUnclosedStreams(); 1148 1149 FSEditLog sourceEditLog = fsns.getFSImage().editLog; 1150 1151 long fromTxId = fsns.getFSImage().getMostRecentCheckpointTxId(); 1152 1153 Collection<EditLogInputStream> streams = null; 1154 try { 1155 streams = sourceEditLog.selectInputStreams(fromTxId + 1, 0); 1156 1157 // Set the nextTxid to the CheckpointTxId+1 1158 newSharedEditLog.setNextTxId(fromTxId + 1); 1159 1160 // Copy all edits after last CheckpointTxId to shared edits dir 1161 for (EditLogInputStream stream : streams) { 1162 LOG.debug("Beginning to copy stream " + stream + " to shared edits"); 1163 FSEditLogOp op; 1164 boolean segmentOpen = false; 1165 while ((op = stream.readOp()) != null) { 1166 if (LOG.isTraceEnabled()) { 1167 LOG.trace("copying op: " + op); 1168 } 1169 if (!segmentOpen) { 1170 newSharedEditLog.startLogSegment(op.txid, false); 1171 segmentOpen = true; 1172 } 1173 1174 newSharedEditLog.logEdit(op); 1175 1176 if (op.opCode == FSEditLogOpCodes.OP_END_LOG_SEGMENT) { 1177 newSharedEditLog.logSync(); 1178 newSharedEditLog.endCurrentLogSegment(false); 1179 LOG.debug("ending log segment because of END_LOG_SEGMENT op in " 1180 + stream); 1181 segmentOpen = false; 1182 } 1183 } 1184 1185 if (segmentOpen) { 1186 LOG.debug("ending log segment because of end of stream in " + stream); 1187 newSharedEditLog.logSync(); 1188 newSharedEditLog.endCurrentLogSegment(false); 1189 segmentOpen = false; 1190 } 1191 } 1192 } finally { 1193 if (streams != null) { 1194 FSEditLog.closeAllStreams(streams); 1195 } 1196 } 1197 } 1198 1199 @VisibleForTesting 1200 public static boolean doRollback(Configuration conf, 1201 boolean isConfirmationNeeded) throws IOException { 1202 String nsId = DFSUtil.getNamenodeNameServiceId(conf); 1203 String namenodeId = HAUtil.getNameNodeId(conf, nsId); 1204 initializeGenericKeys(conf, nsId, namenodeId); 1205 1206 FSNamesystem nsys = new FSNamesystem(conf, new FSImage(conf)); 1207 System.err.print( 1208 "\"rollBack\" will remove the current state of the file system,\n" 1209 + "returning you to the state prior to initiating your recent.\n" 1210 + "upgrade. This action is permanent and cannot be undone. If you\n" 1211 + "are performing a rollback in an HA environment, you should be\n" 1212 + "certain that no NameNode process is running on any host."); 1213 if (isConfirmationNeeded) { 1214 if (!confirmPrompt("Roll back file system state?")) { 1215 System.err.println("Rollback aborted."); 1216 return true; 1217 } 1218 } 1219 nsys.getFSImage().doRollback(nsys); 1220 return false; 1221 } 1222 1223 private static void printUsage(PrintStream out) { 1224 out.println(USAGE + "\n"); 1225 } 1226 1227 @VisibleForTesting 1228 static StartupOption parseArguments(String args[]) { 1229 int argsLen = (args == null) ? 0 : args.length; 1230 StartupOption startOpt = StartupOption.REGULAR; 1231 for(int i=0; i < argsLen; i++) { 1232 String cmd = args[i]; 1233 if (StartupOption.FORMAT.getName().equalsIgnoreCase(cmd)) { 1234 startOpt = StartupOption.FORMAT; 1235 for (i = i + 1; i < argsLen; i++) { 1236 if (args[i].equalsIgnoreCase(StartupOption.CLUSTERID.getName())) { 1237 i++; 1238 if (i >= argsLen) { 1239 // if no cluster id specified, return null 1240 LOG.error("Must specify a valid cluster ID after the " 1241 + StartupOption.CLUSTERID.getName() + " flag"); 1242 return null; 1243 } 1244 String clusterId = args[i]; 1245 // Make sure an id is specified and not another flag 1246 if (clusterId.isEmpty() || 1247 clusterId.equalsIgnoreCase(StartupOption.FORCE.getName()) || 1248 clusterId.equalsIgnoreCase( 1249 StartupOption.NONINTERACTIVE.getName())) { 1250 LOG.error("Must specify a valid cluster ID after the " 1251 + StartupOption.CLUSTERID.getName() + " flag"); 1252 return null; 1253 } 1254 startOpt.setClusterId(clusterId); 1255 } 1256 1257 if (args[i].equalsIgnoreCase(StartupOption.FORCE.getName())) { 1258 startOpt.setForceFormat(true); 1259 } 1260 1261 if (args[i].equalsIgnoreCase(StartupOption.NONINTERACTIVE.getName())) { 1262 startOpt.setInteractiveFormat(false); 1263 } 1264 } 1265 } else if (StartupOption.GENCLUSTERID.getName().equalsIgnoreCase(cmd)) { 1266 startOpt = StartupOption.GENCLUSTERID; 1267 } else if (StartupOption.REGULAR.getName().equalsIgnoreCase(cmd)) { 1268 startOpt = StartupOption.REGULAR; 1269 } else if (StartupOption.BACKUP.getName().equalsIgnoreCase(cmd)) { 1270 startOpt = StartupOption.BACKUP; 1271 } else if (StartupOption.CHECKPOINT.getName().equalsIgnoreCase(cmd)) { 1272 startOpt = StartupOption.CHECKPOINT; 1273 } else if (StartupOption.UPGRADE.getName().equalsIgnoreCase(cmd) 1274 || StartupOption.UPGRADEONLY.getName().equalsIgnoreCase(cmd)) { 1275 startOpt = StartupOption.UPGRADE.getName().equalsIgnoreCase(cmd) ? 1276 StartupOption.UPGRADE : StartupOption.UPGRADEONLY; 1277 /* Can be followed by CLUSTERID with a required parameter or 1278 * RENAMERESERVED with an optional parameter 1279 */ 1280 while (i + 1 < argsLen) { 1281 String flag = args[i + 1]; 1282 if (flag.equalsIgnoreCase(StartupOption.CLUSTERID.getName())) { 1283 if (i + 2 < argsLen) { 1284 i += 2; 1285 startOpt.setClusterId(args[i]); 1286 } else { 1287 LOG.error("Must specify a valid cluster ID after the " 1288 + StartupOption.CLUSTERID.getName() + " flag"); 1289 return null; 1290 } 1291 } else if (flag.equalsIgnoreCase(StartupOption.RENAMERESERVED 1292 .getName())) { 1293 if (i + 2 < argsLen) { 1294 FSImageFormat.setRenameReservedPairs(args[i + 2]); 1295 i += 2; 1296 } else { 1297 FSImageFormat.useDefaultRenameReservedPairs(); 1298 i += 1; 1299 } 1300 } else { 1301 LOG.error("Unknown upgrade flag " + flag); 1302 return null; 1303 } 1304 } 1305 } else if (StartupOption.ROLLINGUPGRADE.getName().equalsIgnoreCase(cmd)) { 1306 startOpt = StartupOption.ROLLINGUPGRADE; 1307 ++i; 1308 if (i >= argsLen) { 1309 LOG.error("Must specify a rolling upgrade startup option " 1310 + RollingUpgradeStartupOption.getAllOptionString()); 1311 return null; 1312 } 1313 startOpt.setRollingUpgradeStartupOption(args[i]); 1314 } else if (StartupOption.ROLLBACK.getName().equalsIgnoreCase(cmd)) { 1315 startOpt = StartupOption.ROLLBACK; 1316 } else if (StartupOption.FINALIZE.getName().equalsIgnoreCase(cmd)) { 1317 startOpt = StartupOption.FINALIZE; 1318 } else if (StartupOption.IMPORT.getName().equalsIgnoreCase(cmd)) { 1319 startOpt = StartupOption.IMPORT; 1320 } else if (StartupOption.BOOTSTRAPSTANDBY.getName().equalsIgnoreCase(cmd)) { 1321 startOpt = StartupOption.BOOTSTRAPSTANDBY; 1322 return startOpt; 1323 } else if (StartupOption.INITIALIZESHAREDEDITS.getName().equalsIgnoreCase(cmd)) { 1324 startOpt = StartupOption.INITIALIZESHAREDEDITS; 1325 for (i = i + 1 ; i < argsLen; i++) { 1326 if (StartupOption.NONINTERACTIVE.getName().equals(args[i])) { 1327 startOpt.setInteractiveFormat(false); 1328 } else if (StartupOption.FORCE.getName().equals(args[i])) { 1329 startOpt.setForceFormat(true); 1330 } else { 1331 LOG.error("Invalid argument: " + args[i]); 1332 return null; 1333 } 1334 } 1335 return startOpt; 1336 } else if (StartupOption.RECOVER.getName().equalsIgnoreCase(cmd)) { 1337 if (startOpt != StartupOption.REGULAR) { 1338 throw new RuntimeException("Can't combine -recover with " + 1339 "other startup options."); 1340 } 1341 startOpt = StartupOption.RECOVER; 1342 while (++i < argsLen) { 1343 if (args[i].equalsIgnoreCase( 1344 StartupOption.FORCE.getName())) { 1345 startOpt.setForce(MetaRecoveryContext.FORCE_FIRST_CHOICE); 1346 } else { 1347 throw new RuntimeException("Error parsing recovery options: " + 1348 "can't understand option \"" + args[i] + "\""); 1349 } 1350 } 1351 } else if (StartupOption.METADATAVERSION.getName().equalsIgnoreCase(cmd)) { 1352 startOpt = StartupOption.METADATAVERSION; 1353 } else { 1354 return null; 1355 } 1356 } 1357 return startOpt; 1358 } 1359 1360 private static void setStartupOption(Configuration conf, StartupOption opt) { 1361 conf.set(DFS_NAMENODE_STARTUP_KEY, opt.name()); 1362 } 1363 1364 static StartupOption getStartupOption(Configuration conf) { 1365 return StartupOption.valueOf(conf.get(DFS_NAMENODE_STARTUP_KEY, 1366 StartupOption.REGULAR.toString())); 1367 } 1368 1369 private static void doRecovery(StartupOption startOpt, Configuration conf) 1370 throws IOException { 1371 String nsId = DFSUtil.getNamenodeNameServiceId(conf); 1372 String namenodeId = HAUtil.getNameNodeId(conf, nsId); 1373 initializeGenericKeys(conf, nsId, namenodeId); 1374 if (startOpt.getForce() < MetaRecoveryContext.FORCE_ALL) { 1375 if (!confirmPrompt("You have selected Metadata Recovery mode. " + 1376 "This mode is intended to recover lost metadata on a corrupt " + 1377 "filesystem. Metadata recovery mode often permanently deletes " + 1378 "data from your HDFS filesystem. Please back up your edit log " + 1379 "and fsimage before trying this!\n\n" + 1380 "Are you ready to proceed? (Y/N)\n")) { 1381 System.err.println("Recovery aborted at user request.\n"); 1382 return; 1383 } 1384 } 1385 MetaRecoveryContext.LOG.info("starting recovery..."); 1386 UserGroupInformation.setConfiguration(conf); 1387 NameNode.initMetrics(conf, startOpt.toNodeRole()); 1388 FSNamesystem fsn = null; 1389 try { 1390 fsn = FSNamesystem.loadFromDisk(conf); 1391 fsn.getFSImage().saveNamespace(fsn); 1392 MetaRecoveryContext.LOG.info("RECOVERY COMPLETE"); 1393 } catch (IOException e) { 1394 MetaRecoveryContext.LOG.info("RECOVERY FAILED: caught exception", e); 1395 throw e; 1396 } catch (RuntimeException e) { 1397 MetaRecoveryContext.LOG.info("RECOVERY FAILED: caught exception", e); 1398 throw e; 1399 } finally { 1400 if (fsn != null) 1401 fsn.close(); 1402 } 1403 } 1404 1405 /** 1406 * Verify that configured directories exist, then print the metadata versions 1407 * of the software and the image. 1408 * 1409 * @param conf configuration to use 1410 * @throws IOException 1411 */ 1412 private static boolean printMetadataVersion(Configuration conf) 1413 throws IOException { 1414 final String nsId = DFSUtil.getNamenodeNameServiceId(conf); 1415 final String namenodeId = HAUtil.getNameNodeId(conf, nsId); 1416 NameNode.initializeGenericKeys(conf, nsId, namenodeId); 1417 final FSImage fsImage = new FSImage(conf); 1418 final FSNamesystem fs = new FSNamesystem(conf, fsImage, false); 1419 return fsImage.recoverTransitionRead( 1420 StartupOption.METADATAVERSION, fs, null); 1421 } 1422 1423 public static NameNode createNameNode(String argv[], Configuration conf) 1424 throws IOException { 1425 LOG.info("createNameNode " + Arrays.asList(argv)); 1426 if (conf == null) 1427 conf = new HdfsConfiguration(); 1428 // Parse out some generic args into Configuration. 1429 GenericOptionsParser hParser = new GenericOptionsParser(conf, argv); 1430 argv = hParser.getRemainingArgs(); 1431 // Parse the rest, NN specific args. 1432 StartupOption startOpt = parseArguments(argv); 1433 if (startOpt == null) { 1434 printUsage(System.err); 1435 return null; 1436 } 1437 setStartupOption(conf, startOpt); 1438 1439 switch (startOpt) { 1440 case FORMAT: { 1441 boolean aborted = format(conf, startOpt.getForceFormat(), 1442 startOpt.getInteractiveFormat()); 1443 terminate(aborted ? 1 : 0); 1444 return null; // avoid javac warning 1445 } 1446 case GENCLUSTERID: { 1447 System.err.println("Generating new cluster id:"); 1448 System.out.println(NNStorage.newClusterID()); 1449 terminate(0); 1450 return null; 1451 } 1452 case FINALIZE: { 1453 System.err.println("Use of the argument '" + StartupOption.FINALIZE + 1454 "' is no longer supported. To finalize an upgrade, start the NN " + 1455 " and then run `hdfs dfsadmin -finalizeUpgrade'"); 1456 terminate(1); 1457 return null; // avoid javac warning 1458 } 1459 case ROLLBACK: { 1460 boolean aborted = doRollback(conf, true); 1461 terminate(aborted ? 1 : 0); 1462 return null; // avoid warning 1463 } 1464 case BOOTSTRAPSTANDBY: { 1465 String toolArgs[] = Arrays.copyOfRange(argv, 1, argv.length); 1466 int rc = BootstrapStandby.run(toolArgs, conf); 1467 terminate(rc); 1468 return null; // avoid warning 1469 } 1470 case INITIALIZESHAREDEDITS: { 1471 boolean aborted = initializeSharedEdits(conf, 1472 startOpt.getForceFormat(), 1473 startOpt.getInteractiveFormat()); 1474 terminate(aborted ? 1 : 0); 1475 return null; // avoid warning 1476 } 1477 case BACKUP: 1478 case CHECKPOINT: { 1479 NamenodeRole role = startOpt.toNodeRole(); 1480 DefaultMetricsSystem.initialize(role.toString().replace(" ", "")); 1481 return new BackupNode(conf, role); 1482 } 1483 case RECOVER: { 1484 NameNode.doRecovery(startOpt, conf); 1485 return null; 1486 } 1487 case METADATAVERSION: { 1488 printMetadataVersion(conf); 1489 terminate(0); 1490 return null; // avoid javac warning 1491 } 1492 case UPGRADEONLY: { 1493 DefaultMetricsSystem.initialize("NameNode"); 1494 new NameNode(conf); 1495 terminate(0); 1496 return null; 1497 } 1498 default: { 1499 DefaultMetricsSystem.initialize("NameNode"); 1500 return new NameNode(conf); 1501 } 1502 } 1503 } 1504 1505 /** 1506 * In federation configuration is set for a set of 1507 * namenode and secondary namenode/backup/checkpointer, which are 1508 * grouped under a logical nameservice ID. The configuration keys specific 1509 * to them have suffix set to configured nameserviceId. 1510 * 1511 * This method copies the value from specific key of format key.nameserviceId 1512 * to key, to set up the generic configuration. Once this is done, only 1513 * generic version of the configuration is read in rest of the code, for 1514 * backward compatibility and simpler code changes. 1515 * 1516 * @param conf 1517 * Configuration object to lookup specific key and to set the value 1518 * to the key passed. Note the conf object is modified 1519 * @param nameserviceId name service Id (to distinguish federated NNs) 1520 * @param namenodeId the namenode ID (to distinguish HA NNs) 1521 * @see DFSUtil#setGenericConf(Configuration, String, String, String...) 1522 */ 1523 public static void initializeGenericKeys(Configuration conf, 1524 String nameserviceId, String namenodeId) { 1525 if ((nameserviceId != null && !nameserviceId.isEmpty()) || 1526 (namenodeId != null && !namenodeId.isEmpty())) { 1527 if (nameserviceId != null) { 1528 conf.set(DFS_NAMESERVICE_ID, nameserviceId); 1529 } 1530 if (namenodeId != null) { 1531 conf.set(DFS_HA_NAMENODE_ID_KEY, namenodeId); 1532 } 1533 1534 DFSUtil.setGenericConf(conf, nameserviceId, namenodeId, 1535 NAMENODE_SPECIFIC_KEYS); 1536 DFSUtil.setGenericConf(conf, nameserviceId, null, 1537 NAMESERVICE_SPECIFIC_KEYS); 1538 } 1539 1540 // If the RPC address is set use it to (re-)configure the default FS 1541 if (conf.get(DFS_NAMENODE_RPC_ADDRESS_KEY) != null) { 1542 URI defaultUri = URI.create(HdfsConstants.HDFS_URI_SCHEME + "://" 1543 + conf.get(DFS_NAMENODE_RPC_ADDRESS_KEY)); 1544 conf.set(FS_DEFAULT_NAME_KEY, defaultUri.toString()); 1545 LOG.debug("Setting " + FS_DEFAULT_NAME_KEY + " to " + defaultUri.toString()); 1546 } 1547 } 1548 1549 /** 1550 * Get the name service Id for the node 1551 * @return name service Id or null if federation is not configured 1552 */ 1553 protected String getNameServiceId(Configuration conf) { 1554 return DFSUtil.getNamenodeNameServiceId(conf); 1555 } 1556 1557 /** 1558 */ 1559 public static void main(String argv[]) throws Exception { 1560 if (DFSUtil.parseHelpArgument(argv, NameNode.USAGE, System.out, true)) { 1561 System.exit(0); 1562 } 1563 1564 try { 1565 StringUtils.startupShutdownMessage(NameNode.class, argv, LOG); 1566 NameNode namenode = createNameNode(argv, null); 1567 if (namenode != null) { 1568 namenode.join(); 1569 } 1570 } catch (Throwable e) { 1571 LOG.error("Failed to start namenode.", e); 1572 terminate(1, e); 1573 } 1574 } 1575 1576 synchronized void monitorHealth() 1577 throws HealthCheckFailedException, AccessControlException { 1578 namesystem.checkSuperuserPrivilege(); 1579 if (!haEnabled) { 1580 return; // no-op, if HA is not enabled 1581 } 1582 getNamesystem().checkAvailableResources(); 1583 if (!getNamesystem().nameNodeHasResourcesAvailable()) { 1584 throw new HealthCheckFailedException( 1585 "The NameNode has no resources available"); 1586 } 1587 } 1588 1589 synchronized void transitionToActive() 1590 throws ServiceFailedException, AccessControlException { 1591 namesystem.checkSuperuserPrivilege(); 1592 if (!haEnabled) { 1593 throw new ServiceFailedException("HA for namenode is not enabled"); 1594 } 1595 state.setState(haContext, ACTIVE_STATE); 1596 } 1597 1598 synchronized void transitionToStandby() 1599 throws ServiceFailedException, AccessControlException { 1600 namesystem.checkSuperuserPrivilege(); 1601 if (!haEnabled) { 1602 throw new ServiceFailedException("HA for namenode is not enabled"); 1603 } 1604 state.setState(haContext, STANDBY_STATE); 1605 } 1606 1607 synchronized HAServiceStatus getServiceStatus() 1608 throws ServiceFailedException, AccessControlException { 1609 namesystem.checkSuperuserPrivilege(); 1610 if (!haEnabled) { 1611 throw new ServiceFailedException("HA for namenode is not enabled"); 1612 } 1613 if (state == null) { 1614 return new HAServiceStatus(HAServiceState.INITIALIZING); 1615 } 1616 HAServiceState retState = state.getServiceState(); 1617 HAServiceStatus ret = new HAServiceStatus(retState); 1618 if (retState == HAServiceState.STANDBY) { 1619 String safemodeTip = namesystem.getSafeModeTip(); 1620 if (!safemodeTip.isEmpty()) { 1621 ret.setNotReadyToBecomeActive( 1622 "The NameNode is in safemode. " + 1623 safemodeTip); 1624 } else { 1625 ret.setReadyToBecomeActive(); 1626 } 1627 } else if (retState == HAServiceState.ACTIVE) { 1628 ret.setReadyToBecomeActive(); 1629 } else { 1630 ret.setNotReadyToBecomeActive("State is " + state); 1631 } 1632 return ret; 1633 } 1634 1635 synchronized HAServiceState getServiceState() { 1636 if (state == null) { 1637 return HAServiceState.INITIALIZING; 1638 } 1639 return state.getServiceState(); 1640 } 1641 1642 /** 1643 * Register NameNodeStatusMXBean 1644 */ 1645 private void registerNNSMXBean() { 1646 nameNodeStatusBeanName = MBeans.register("NameNode", "NameNodeStatus", this); 1647 } 1648 1649 @Override // NameNodeStatusMXBean 1650 public String getNNRole() { 1651 String roleStr = ""; 1652 NamenodeRole role = getRole(); 1653 if (null != role) { 1654 roleStr = role.toString(); 1655 } 1656 return roleStr; 1657 } 1658 1659 @Override // NameNodeStatusMXBean 1660 public String getState() { 1661 String servStateStr = ""; 1662 HAServiceState servState = getServiceState(); 1663 if (null != servState) { 1664 servStateStr = servState.toString(); 1665 } 1666 return servStateStr; 1667 } 1668 1669 @Override // NameNodeStatusMXBean 1670 public String getHostAndPort() { 1671 return getNameNodeAddressHostPortString(); 1672 } 1673 1674 @Override // NameNodeStatusMXBean 1675 public boolean isSecurityEnabled() { 1676 return UserGroupInformation.isSecurityEnabled(); 1677 } 1678 1679 @Override // NameNodeStatusMXBean 1680 public long getLastHATransitionTime() { 1681 return state.getLastHATransitionTime(); 1682 } 1683 1684 /** 1685 * Shutdown the NN immediately in an ungraceful way. Used when it would be 1686 * unsafe for the NN to continue operating, e.g. during a failed HA state 1687 * transition. 1688 * 1689 * @param t exception which warrants the shutdown. Printed to the NN log 1690 * before exit. 1691 * @throws ExitException thrown only for testing. 1692 */ 1693 protected synchronized void doImmediateShutdown(Throwable t) 1694 throws ExitException { 1695 String message = "Error encountered requiring NN shutdown. " + 1696 "Shutting down immediately."; 1697 try { 1698 LOG.error(message, t); 1699 } catch (Throwable ignored) { 1700 // This is unlikely to happen, but there's nothing we can do if it does. 1701 } 1702 terminate(1, t); 1703 } 1704 1705 /** 1706 * Class used to expose {@link NameNode} as context to {@link HAState} 1707 */ 1708 protected class NameNodeHAContext implements HAContext { 1709 @Override 1710 public void setState(HAState s) { 1711 state = s; 1712 } 1713 1714 @Override 1715 public HAState getState() { 1716 return state; 1717 } 1718 1719 @Override 1720 public void startActiveServices() throws IOException { 1721 try { 1722 namesystem.startActiveServices(); 1723 startTrashEmptier(conf); 1724 } catch (Throwable t) { 1725 doImmediateShutdown(t); 1726 } 1727 } 1728 1729 @Override 1730 public void stopActiveServices() throws IOException { 1731 try { 1732 if (namesystem != null) { 1733 namesystem.stopActiveServices(); 1734 } 1735 stopTrashEmptier(); 1736 } catch (Throwable t) { 1737 doImmediateShutdown(t); 1738 } 1739 } 1740 1741 @Override 1742 public void startStandbyServices() throws IOException { 1743 try { 1744 namesystem.startStandbyServices(conf); 1745 } catch (Throwable t) { 1746 doImmediateShutdown(t); 1747 } 1748 } 1749 1750 @Override 1751 public void prepareToStopStandbyServices() throws ServiceFailedException { 1752 try { 1753 namesystem.prepareToStopStandbyServices(); 1754 } catch (Throwable t) { 1755 doImmediateShutdown(t); 1756 } 1757 } 1758 1759 @Override 1760 public void stopStandbyServices() throws IOException { 1761 try { 1762 if (namesystem != null) { 1763 namesystem.stopStandbyServices(); 1764 } 1765 } catch (Throwable t) { 1766 doImmediateShutdown(t); 1767 } 1768 } 1769 1770 @Override 1771 public void writeLock() { 1772 namesystem.writeLock(); 1773 namesystem.lockRetryCache(); 1774 } 1775 1776 @Override 1777 public void writeUnlock() { 1778 namesystem.unlockRetryCache(); 1779 namesystem.writeUnlock(); 1780 } 1781 1782 /** Check if an operation of given category is allowed */ 1783 @Override 1784 public void checkOperation(final OperationCategory op) 1785 throws StandbyException { 1786 state.checkOperation(haContext, op); 1787 } 1788 1789 @Override 1790 public boolean allowStaleReads() { 1791 return allowStaleStandbyReads; 1792 } 1793 1794 } 1795 1796 public boolean isStandbyState() { 1797 return (state.equals(STANDBY_STATE)); 1798 } 1799 1800 public boolean isActiveState() { 1801 return (state.equals(ACTIVE_STATE)); 1802 } 1803 1804 /** 1805 * Returns whether the NameNode is completely started 1806 */ 1807 boolean isStarted() { 1808 return this.started.get(); 1809 } 1810 1811 /** 1812 * Check that a request to change this node's HA state is valid. 1813 * In particular, verifies that, if auto failover is enabled, non-forced 1814 * requests from the HAAdmin CLI are rejected, and vice versa. 1815 * 1816 * @param req the request to check 1817 * @throws AccessControlException if the request is disallowed 1818 */ 1819 void checkHaStateChange(StateChangeRequestInfo req) 1820 throws AccessControlException { 1821 boolean autoHaEnabled = conf.getBoolean(DFS_HA_AUTO_FAILOVER_ENABLED_KEY, 1822 DFS_HA_AUTO_FAILOVER_ENABLED_DEFAULT); 1823 switch (req.getSource()) { 1824 case REQUEST_BY_USER: 1825 if (autoHaEnabled) { 1826 throw new AccessControlException( 1827 "Manual HA control for this NameNode is disallowed, because " + 1828 "automatic HA is enabled."); 1829 } 1830 break; 1831 case REQUEST_BY_USER_FORCED: 1832 if (autoHaEnabled) { 1833 LOG.warn("Allowing manual HA control from " + 1834 Server.getRemoteAddress() + 1835 " even though automatic HA is enabled, because the user " + 1836 "specified the force flag"); 1837 } 1838 break; 1839 case REQUEST_BY_ZKFC: 1840 if (!autoHaEnabled) { 1841 throw new AccessControlException( 1842 "Request from ZK failover controller at " + 1843 Server.getRemoteAddress() + " denied since automatic HA " + 1844 "is not enabled"); 1845 } 1846 break; 1847 } 1848 } 1849}