|
21 | 21 | import java.net.InetSocketAddress; |
22 | 22 | import java.nio.file.Files; |
23 | 23 | import java.nio.file.Path; |
| 24 | +import java.nio.file.Paths; |
24 | 25 | import java.nio.file.attribute.PosixFilePermissions; |
25 | 26 | import java.util.Collection; |
26 | 27 | import org.apache.hadoop.fs.permission.FsPermission; |
27 | 28 | import org.apache.hadoop.hdds.HddsConfigKeys; |
28 | 29 | import org.apache.hadoop.hdds.conf.ConfigurationSource; |
29 | 30 | import org.apache.hadoop.hdds.conf.OzoneConfiguration; |
| 31 | +import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeType; |
30 | 32 | import org.apache.hadoop.hdds.recon.ReconConfigKeys; |
31 | 33 | import org.apache.hadoop.hdds.scm.ScmConfigKeys; |
32 | 34 | import org.apache.hadoop.ipc_.RPC; |
33 | 35 | import org.apache.hadoop.ipc_.Server; |
34 | 36 | import org.apache.hadoop.ozone.OzoneConfigKeys; |
| 37 | +import org.apache.hadoop.ozone.OzoneConsts; |
35 | 38 | import org.apache.hadoop.security.UserGroupInformation; |
36 | 39 | import org.slf4j.Logger; |
37 | 40 | import org.slf4j.LoggerFactory; |
@@ -300,11 +303,136 @@ public static String getRemoteUserName() { |
300 | 303 | return remoteUser != null ? remoteUser.getUserName() : null; |
301 | 304 | } |
302 | 305 |
|
303 | | - public static String getDefaultRatisDirectory(ConfigurationSource conf) { |
| 306 | + /** |
| 307 | + * Get the default Ratis directory for a component when the specific |
| 308 | + * configuration is not set. This creates a component-specific subdirectory |
| 309 | + * under ozone.metadata.dirs to avoid conflicts when multiple components |
| 310 | + * are colocated on the same host. |
| 311 | + * |
| 312 | + * <p>For backward compatibility during upgrades, this method checks for |
| 313 | + * existing Ratis data in old locations before using the new component-specific |
| 314 | + * location. See {@link #findExistingRatisDirectory} for details on old locations. |
| 315 | + * |
| 316 | + * @param conf Configuration source |
| 317 | + * @param nodeType Type of the node component |
| 318 | + * @return Path to the component-specific ratis directory |
| 319 | + */ |
| 320 | + public static String getDefaultRatisDirectory(ConfigurationSource conf, |
| 321 | + NodeType nodeType) { |
304 | 322 | LOG.warn("Storage directory for Ratis is not configured. It is a good " + |
305 | 323 | "idea to map this to an SSD disk. Falling back to {}", |
306 | 324 | HddsConfigKeys.OZONE_METADATA_DIRS); |
307 | 325 | File metaDirPath = ServerUtils.getOzoneMetaDirPath(conf); |
308 | | - return (new File(metaDirPath, "ratis")).getPath(); |
| 326 | + |
| 327 | + // Check for existing Ratis data from old versions for backward compatibility |
| 328 | + String existingDir = findExistingRatisDirectory(metaDirPath, nodeType); |
| 329 | + if (existingDir != null) { |
| 330 | + return existingDir; |
| 331 | + } |
| 332 | + |
| 333 | + // Use new component-specific location for new installations |
| 334 | + String componentName = getComponentName(nodeType); |
| 335 | + return Paths.get(metaDirPath.getPath(), componentName + ".ratis").toString(); |
| 336 | + } |
| 337 | + |
| 338 | + /** |
| 339 | + * Checks for existing Ratis directories from previous versions for backward |
| 340 | + * compatibility during upgrades. |
| 341 | + * |
| 342 | + * <p>Older versions of Ozone used different directory structures: |
| 343 | + * <ul> |
| 344 | + * <li>Versions up to 2.0.0: Shared {@code <ozone.metadata.dirs>/ratis} for all components</li> |
| 345 | + * <li>Some SCM versions: Used {@code <ozone.metadata.dirs>/scm-ha}</li> |
| 346 | + * </ul> |
| 347 | + * |
| 348 | + * @param metaDirPath The ozone metadata directory path |
| 349 | + * @param nodeType Type of the node component |
| 350 | + * @return Path to existing old Ratis directory if found, null otherwise |
| 351 | + */ |
| 352 | + private static String findExistingRatisDirectory(File metaDirPath, |
| 353 | + NodeType nodeType) { |
| 354 | + // Check component-specific old location (SCM used scm-ha in some versions) |
| 355 | + if ("scm".equals(getComponentName(nodeType))) { |
| 356 | + File oldScmRatisDir = new File(metaDirPath, "scm-ha"); |
| 357 | + if (isNonEmptyDirectory(oldScmRatisDir)) { |
| 358 | + LOG.info("Found existing SCM Ratis directory at old location: {}. " + |
| 359 | + "Using it for backward compatibility during upgrade.", |
| 360 | + oldScmRatisDir.getPath()); |
| 361 | + return oldScmRatisDir.getPath(); |
| 362 | + } |
| 363 | + } |
| 364 | + |
| 365 | + // Check old shared Ratis location (used by version 2.0.0 and earlier) |
| 366 | + // All components (OM, SCM) shared /data/metadata/ratis |
| 367 | + File oldSharedRatisDir = new File(metaDirPath, "ratis"); |
| 368 | + if (isNonEmptyDirectory(oldSharedRatisDir)) { |
| 369 | + LOG.info("Found existing Ratis directory at old shared location: {}. " + |
| 370 | + "Using it for backward compatibility during upgrade.", |
| 371 | + oldSharedRatisDir.getPath()); |
| 372 | + return oldSharedRatisDir.getPath(); |
| 373 | + } |
| 374 | + |
| 375 | + return null; |
| 376 | + } |
| 377 | + |
| 378 | + /** |
| 379 | + * Converts NodeType enum to the component name string used for directory naming. |
| 380 | + * |
| 381 | + * @param nodeType Type of the node component |
| 382 | + * @return Component name string (e.g., "om", "scm", "dn", "recon") |
| 383 | + */ |
| 384 | + private static String getComponentName(NodeType nodeType) { |
| 385 | + switch (nodeType) { |
| 386 | + case OM: |
| 387 | + return "om"; |
| 388 | + case SCM: |
| 389 | + return "scm"; |
| 390 | + case DATANODE: |
| 391 | + return "dn"; |
| 392 | + case RECON: |
| 393 | + return "recon"; |
| 394 | + default: |
| 395 | + throw new IllegalArgumentException("Unknown NodeType: " + nodeType); |
| 396 | + } |
| 397 | + } |
| 398 | + |
| 399 | + /** |
| 400 | + * Get the default Ratis snapshot directory for a component when the specific |
| 401 | + * configuration is not set. This creates a component-specific subdirectory |
| 402 | + * under ozone.metadata.dirs to avoid conflicts when multiple components |
| 403 | + * are colocated on the same host. |
| 404 | + * |
| 405 | + * New path format: {ozone.metadata.dirs}/{NodeType}.ratis.snapshot |
| 406 | + * eg: /data/metadata/om.ratis.snapshot |
| 407 | + * /data/metadata/scm.ratis.snapshot |
| 408 | + * |
| 409 | + * @param conf Configuration source |
| 410 | + * @param nodeType Type of the node component |
| 411 | + * @return Path to the component-specific ratis snapshot directory |
| 412 | + */ |
| 413 | + public static String getDefaultRatisSnapshotDirectory(ConfigurationSource conf, |
| 414 | + NodeType nodeType) { |
| 415 | + LOG.warn("Snapshot directory for Ratis is not configured. Falling back to {}", |
| 416 | + HddsConfigKeys.OZONE_METADATA_DIRS); |
| 417 | + File metaDirPath = ServerUtils.getOzoneMetaDirPath(conf); |
| 418 | + |
| 419 | + // Use component-specific location |
| 420 | + String componentName = getComponentName(nodeType); |
| 421 | + return Paths.get(metaDirPath.getPath(), |
| 422 | + componentName + ".ratis." + OzoneConsts.OZONE_RATIS_SNAPSHOT_DIR).toString(); |
| 423 | + } |
| 424 | + |
| 425 | + /** |
| 426 | + * Checks if a directory exists and is non-empty. |
| 427 | + * |
| 428 | + * @param dir Directory to check |
| 429 | + * @return true if directory exists and contains at least one file |
| 430 | + */ |
| 431 | + private static boolean isNonEmptyDirectory(File dir) { |
| 432 | + if (dir != null && dir.exists() && dir.isDirectory()) { |
| 433 | + File[] files = dir.listFiles(); |
| 434 | + return files != null && files.length > 0; |
| 435 | + } |
| 436 | + return false; |
309 | 437 | } |
310 | 438 | } |
0 commit comments