diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java index 5e31bee94fc3..d7d3b6617fbb 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancer.java @@ -20,6 +20,7 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.conf.StorageUnit; +import org.apache.hadoop.hdds.fs.DUFactory; import org.apache.hadoop.hdds.protocol.DatanodeDetails; import org.apache.hadoop.hdds.scm.PlacementPolicy; import org.apache.hadoop.hdds.scm.ScmConfigKeys; @@ -124,7 +125,8 @@ public ContainerBalancer( this.containerManager = containerManager; this.replicationManager = replicationManager; this.ozoneConfiguration = ozoneConfiguration; - this.config = new ContainerBalancerConfiguration(ozoneConfiguration); + this.config = ozoneConfiguration. + getObject(ContainerBalancerConfiguration.class); this.metrics = ContainerBalancerMetrics.create(); this.scmContext = scmContext; @@ -155,7 +157,7 @@ public boolean start(ContainerBalancerConfiguration balancerConfiguration) { balancerRunning = true; this.config = balancerConfiguration; - this.ozoneConfiguration = config.getOzoneConfiguration(); + validateConfiguration(config); LOG.info("Starting Container Balancer...{}", this); //we should start a new balancer thread async @@ -764,6 +766,31 @@ public void stop() { LOG.info("Container Balancer stopped successfully."); } + private void validateConfiguration(ContainerBalancerConfiguration conf) { + // maxSizeEnteringTarget and maxSizeLeavingSource should by default be + // greater than container size + long size = (long) ozoneConfiguration.getStorageSize( + ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE, + ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, StorageUnit.BYTES); + + if (conf.getMaxSizeEnteringTarget() <= size) { + LOG.info("MaxSizeEnteringTarget should be larger than " + + "ozone.scm.container.size"); + } + if (conf.getMaxSizeLeavingSource() <= size) { + LOG.info("MaxSizeLeavingSource should be larger than " + + "ozone.scm.container.size"); + } + + // balancing interval should be greater than DUFactory refresh period + DUFactory.Conf duConf = ozoneConfiguration.getObject(DUFactory.Conf.class); + long balancingInterval = duConf.getRefreshPeriod().toMillis(); + if (conf.getBalancingInterval().toMillis() <= balancingInterval) { + LOG.info("balancing.iteration.interval should be larger than " + + "hdds.datanode.du.refresh.period."); + } + } + public void setNodeManager(NodeManager nodeManager) { this.nodeManager = nodeManager; } diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerConfiguration.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerConfiguration.java index 698b3b0ef7aa..a51e0bd567df 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerConfiguration.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerConfiguration.java @@ -18,15 +18,10 @@ package org.apache.hadoop.hdds.scm.container.balancer; -import com.google.common.base.Preconditions; import org.apache.hadoop.hdds.conf.Config; import org.apache.hadoop.hdds.conf.ConfigGroup; import org.apache.hadoop.hdds.conf.ConfigTag; import org.apache.hadoop.hdds.conf.ConfigType; -import org.apache.hadoop.hdds.conf.OzoneConfiguration; -import org.apache.hadoop.hdds.conf.StorageUnit; -import org.apache.hadoop.hdds.fs.DUFactory; -import org.apache.hadoop.hdds.scm.ScmConfigKeys; import org.apache.hadoop.hdds.scm.container.ContainerID; import org.apache.hadoop.ozone.OzoneConsts; import org.slf4j.Logger; @@ -37,7 +32,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -47,7 +41,6 @@ public final class ContainerBalancerConfiguration { private static final Logger LOG = LoggerFactory.getLogger(ContainerBalancerConfiguration.class); - private OzoneConfiguration ozoneConfiguration; @Config(key = "utilization.threshold", type = ConfigType.AUTO, defaultValue = "0.1", tags = {ConfigTag.BALANCER}, @@ -73,19 +66,19 @@ public final class ContainerBalancerConfiguration { private long maxSizeToMovePerIteration = 30 * OzoneConsts.GB; @Config(key = "size.entering.target.max", type = ConfigType.SIZE, - defaultValue = "", tags = {ConfigTag.BALANCER}, description = "The " + + defaultValue = "26GB", tags = {ConfigTag.BALANCER}, description = "The " + "maximum size that can enter a target datanode in each " + "iteration while balancing. This is the sum of data from multiple " + - "sources. The default value is greater than the configured" + - " (or default) ozone.scm.container.size by 1GB.") + "sources. The value must be greater than the configured" + + " (or default) ozone.scm.container.size.") private long maxSizeEnteringTarget; @Config(key = "size.leaving.source.max", type = ConfigType.SIZE, - defaultValue = "", tags = {ConfigTag.BALANCER}, description = "The " + + defaultValue = "26GB", tags = {ConfigTag.BALANCER}, description = "The " + "maximum size that can leave a source datanode in each " + "iteration while balancing. This is the sum of data moving to multiple " + - "targets. The default value is greater than the configured" + - " (or default) ozone.scm.container.size by 1GB.") + "targets. The value must be greater than the configured" + + " (or default) ozone.scm.container.size.") private long maxSizeLeavingSource; @Config(key = "idle.iterations", type = ConfigType.INT, @@ -99,13 +92,13 @@ public final class ContainerBalancerConfiguration { private String excludeContainers = ""; @Config(key = "move.timeout", type = ConfigType.TIME, defaultValue = "30m", - timeUnit = TimeUnit.MINUTES, tags = {ConfigTag.BALANCER}, description = + tags = {ConfigTag.BALANCER}, description = "The amount of time in minutes to allow a single container to move " + "from source to target.") private long moveTimeout = Duration.ofMinutes(30).toMillis(); @Config(key = "balancing.iteration.interval", type = ConfigType.TIME, - defaultValue = "1h", timeUnit = TimeUnit.MINUTES, tags = { + defaultValue = "70m", tags = { ConfigTag.BALANCER}, description = "The interval period between each " + "iteration of Container Balancer.") private long balancingInterval; @@ -131,33 +124,6 @@ public final class ContainerBalancerConfiguration { "This configuration is false by default.") private boolean networkTopologyEnable = false; - private DUFactory.Conf duConf; - - /** - * Create configuration with default values. - * - * @param config Ozone configuration - */ - public ContainerBalancerConfiguration(OzoneConfiguration config) { - Preconditions.checkNotNull(config, - "OzoneConfiguration should not be null."); - this.ozoneConfiguration = config; - - // maxSizeEnteringTarget and maxSizeLeavingSource should by default be - // greater than container size - long size = (long) ozoneConfiguration.getStorageSize( - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE, - ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, StorageUnit.GB) + - OzoneConsts.GB; - maxSizeEnteringTarget = size; - maxSizeLeavingSource = size; - - // balancing interval should be greater than DUFactory refresh period - duConf = ozoneConfiguration.getObject(DUFactory.Conf.class); - balancingInterval = duConf.getRefreshPeriod().toMillis() + - Duration.ofMinutes(10).toMillis(); - } - /** * Gets the threshold value for Container Balancer. * @@ -324,12 +290,7 @@ public Duration getBalancingInterval() { } public void setBalancingInterval(Duration balancingInterval) { - if (balancingInterval.toMillis() > duConf.getRefreshPeriod().toMillis()) { - this.balancingInterval = balancingInterval.toMillis(); - } else { - LOG.warn("Balancing interval duration must be greater than du refresh " + - "period, {} milliseconds", duConf.getRefreshPeriod().toMillis()); - } + this.balancingInterval = balancingInterval.toMillis(); } /** @@ -381,15 +342,6 @@ public void setExcludeNodes(String excludeNodes) { this.excludeNodes = excludeNodes; } - /** - * Gets the {@link OzoneConfiguration} using which this configuration was - * constructed. - * @return the {@link OzoneConfiguration} being used by this configuration - */ - public OzoneConfiguration getOzoneConfiguration() { - return this.ozoneConfiguration; - } - @Override public String toString() { return String.format("Container Balancer Configuration values:%n" + diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java index 2c6bdd50b820..4006a17eae0e 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java @@ -751,7 +751,7 @@ public boolean startContainerBalancer( Optional maxSizeLeavingSource) throws IOException { getScm().checkAdminAccess(getRemoteUser()); ContainerBalancerConfiguration cbc = - new ContainerBalancerConfiguration(scm.getConfiguration()); + scm.getConfiguration().getObject(ContainerBalancerConfiguration.class); if (threshold.isPresent()) { double tsd = threshold.get(); Preconditions.checkState(tsd >= 0.0D && tsd < 1.0D, diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancer.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancer.java index c2978b20f069..a4776e9504d0 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancer.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/balancer/TestContainerBalancer.java @@ -103,7 +103,8 @@ public void setup() throws SCMException, NodeNotFoundException { containerManager = Mockito.mock(ContainerManager.class); replicationManager = Mockito.mock(ReplicationManager.class); - balancerConfiguration = new ContainerBalancerConfiguration(conf); + balancerConfiguration = + conf.getObject(ContainerBalancerConfiguration.class); balancerConfiguration.setThreshold(0.1); balancerConfiguration.setIdleIteration(1); balancerConfiguration.setMaxDatanodesRatioToInvolvePerIteration(1.0d); @@ -488,8 +489,10 @@ public void balancerShouldObeyMaxSizeEnteringTargetLimit() { Assert.assertTrue(containerBalancer.getSourceToTargetMap().isEmpty()); // some containers should be selected when using default values - containerBalancer.start( - new ContainerBalancerConfiguration(new OzoneConfiguration())); + OzoneConfiguration ozoneConfiguration = new OzoneConfiguration(); + ContainerBalancerConfiguration cbc = ozoneConfiguration. + getObject(ContainerBalancerConfiguration.class); + containerBalancer.start(cbc); // waiting for balance completed. // TODO: this is a temporary implementation for now @@ -591,6 +594,23 @@ public void balancerShouldFollowExcludeAndIncludeDatanodesConfigurations() { } } + @Test + public void testContainerBalancerConfiguration() { + OzoneConfiguration ozoneConfiguration = new OzoneConfiguration(); + ozoneConfiguration.set("ozone.scm.container.size", "5GB"); + ozoneConfiguration.setDouble( + "hdds.container.balancer.utilization.threshold", 0.01); + + ContainerBalancerConfiguration cbConf = + ozoneConfiguration.getObject(ContainerBalancerConfiguration.class); + Assert.assertEquals(cbConf.getThreshold(), 0.01d, 0.001); + + Assert.assertEquals(cbConf.getMaxSizeLeavingSource(), + 26 * 1024 * 1024 * 1024L); + + Assert.assertEquals(cbConf.getMoveTimeout().toMillis(), 30 * 60 * 1000); + } + /** * Determines unBalanced nodes, that is, over and under utilized nodes, * according to the generated utilization values for nodes and the threshold.