|
22 | 22 | import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeOperationalState.IN_SERVICE; |
23 | 23 | import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.HEALTHY; |
24 | 24 | import static org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState.HEALTHY_READONLY; |
| 25 | +import static org.apache.hadoop.hdds.scm.SCMCommonPlacementPolicy.hasEnoughSpace; |
25 | 26 |
|
26 | 27 | import com.google.common.annotations.VisibleForTesting; |
27 | 28 | import com.google.common.base.Preconditions; |
|
51 | 52 | import javax.management.ObjectName; |
52 | 53 | import org.apache.hadoop.hdds.HddsConfigKeys; |
53 | 54 | import org.apache.hadoop.hdds.conf.OzoneConfiguration; |
| 55 | +import org.apache.hadoop.hdds.conf.StorageUnit; |
54 | 56 | import org.apache.hadoop.hdds.protocol.DatanodeDetails; |
55 | 57 | import org.apache.hadoop.hdds.protocol.DatanodeID; |
| 58 | +import org.apache.hadoop.hdds.protocol.proto.HddsProtos; |
56 | 59 | import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeOperationalState; |
57 | 60 | import org.apache.hadoop.hdds.protocol.proto.HddsProtos.NodeState; |
58 | 61 | import org.apache.hadoop.hdds.protocol.proto.HddsProtos.StorageTypeProto; |
|
67 | 70 | import org.apache.hadoop.hdds.scm.ScmConfigKeys; |
68 | 71 | import org.apache.hadoop.hdds.scm.VersionInfo; |
69 | 72 | import org.apache.hadoop.hdds.scm.container.ContainerID; |
| 73 | +import org.apache.hadoop.hdds.scm.container.ContainerInfo; |
70 | 74 | import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeMetric; |
71 | 75 | import org.apache.hadoop.hdds.scm.container.placement.metrics.SCMNodeStat; |
72 | 76 | import org.apache.hadoop.hdds.scm.events.SCMEvents; |
|
84 | 88 | import org.apache.hadoop.hdds.upgrade.HDDSLayoutVersionManager; |
85 | 89 | import org.apache.hadoop.ipc.Server; |
86 | 90 | import org.apache.hadoop.metrics2.util.MBeans; |
| 91 | +import org.apache.hadoop.ozone.OzoneConfigKeys; |
87 | 92 | import org.apache.hadoop.ozone.OzoneConsts; |
88 | 93 | import org.apache.hadoop.ozone.protocol.VersionResponse; |
89 | 94 | import org.apache.hadoop.ozone.protocol.commands.CommandForDatanode; |
@@ -122,6 +127,7 @@ public class SCMNodeManager implements NodeManager { |
122 | 127 | private final SCMNodeMetrics metrics; |
123 | 128 | // Node manager MXBean |
124 | 129 | private ObjectName nmInfoBean; |
| 130 | + private final OzoneConfiguration conf; |
125 | 131 | private final SCMStorageConfig scmStorageConfig; |
126 | 132 | private final NetworkTopology clusterMap; |
127 | 133 | private final Function<String, String> nodeResolver; |
@@ -170,6 +176,7 @@ public SCMNodeManager( |
170 | 176 | SCMContext scmContext, |
171 | 177 | HDDSLayoutVersionManager layoutVersionManager, |
172 | 178 | Function<String, String> nodeResolver) { |
| 179 | + this.conf = conf; |
173 | 180 | this.scmNodeEventPublisher = eventPublisher; |
174 | 181 | this.nodeStateManager = new NodeStateManager(conf, eventPublisher, |
175 | 182 | layoutVersionManager, scmContext); |
@@ -1274,6 +1281,8 @@ public Map<String, String> getNodeStatistics() { |
1274 | 1281 | nodeStateStatistics(nodeStatistics); |
1275 | 1282 | // Statistics node space |
1276 | 1283 | nodeSpaceStatistics(nodeStatistics); |
| 1284 | + // Statistics node readOnly |
| 1285 | + nodeOutOfSpaceStatistics(nodeStatistics); |
1277 | 1286 | // todo: Statistics of other instances |
1278 | 1287 | return nodeStatistics; |
1279 | 1288 | } |
@@ -1361,6 +1370,49 @@ private void nodeSpaceStatistics(Map<String, String> nodeStatics) { |
1361 | 1370 | nodeStatics.put(SpaceStatistics.NON_SCM_USED.getLabel(), nonScmUsed); |
1362 | 1371 | } |
1363 | 1372 |
|
| 1373 | + private void nodeOutOfSpaceStatistics(Map<String, String> nodeStatics) { |
| 1374 | + List<DatanodeInfo> allNodes = getAllNodes(); |
| 1375 | + long blockSize = (long) conf.getStorageSize( |
| 1376 | + OzoneConfigKeys.OZONE_SCM_BLOCK_SIZE, |
| 1377 | + OzoneConfigKeys.OZONE_SCM_BLOCK_SIZE_DEFAULT, |
| 1378 | + StorageUnit.BYTES); |
| 1379 | + long minRatisVolumeSizeBytes = (long) conf.getStorageSize( |
| 1380 | + ScmConfigKeys.OZONE_DATANODE_RATIS_VOLUME_FREE_SPACE_MIN, |
| 1381 | + ScmConfigKeys.OZONE_DATANODE_RATIS_VOLUME_FREE_SPACE_MIN_DEFAULT, |
| 1382 | + StorageUnit.BYTES); |
| 1383 | + long containerSize = (long) conf.getStorageSize( |
| 1384 | + ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE, |
| 1385 | + ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, |
| 1386 | + StorageUnit.BYTES); |
| 1387 | + |
| 1388 | + int nodeOutOfSpaceCount = (int) allNodes.parallelStream() |
| 1389 | + .filter(dn -> !hasEnoughSpace(dn, minRatisVolumeSizeBytes, containerSize, conf) |
| 1390 | + && !hasContainerWithSpace(dn, blockSize, containerSize)) |
| 1391 | + .count(); |
| 1392 | + |
| 1393 | + nodeStatics.put("NodesOutOfSpace", String.valueOf(nodeOutOfSpaceCount)); |
| 1394 | + } |
| 1395 | + |
| 1396 | + /** |
| 1397 | + * Check if a datanode has any OPEN container with enough space to accept new blocks. |
| 1398 | + */ |
| 1399 | + private boolean hasContainerWithSpace(DatanodeInfo dnInfo, long blockSize, long containerSize) { |
| 1400 | + try { |
| 1401 | + Set<ContainerID> containers = getContainers(dnInfo); |
| 1402 | + for (ContainerID containerID : containers) { |
| 1403 | + ContainerInfo containerInfo = scmContext.getScm().getContainerManager().getContainer(containerID); |
| 1404 | + |
| 1405 | + if (containerInfo.getState() == HddsProtos.LifeCycleState.OPEN && |
| 1406 | + containerInfo.getUsedBytes() + blockSize <= containerSize) { |
| 1407 | + return true; |
| 1408 | + } |
| 1409 | + } |
| 1410 | + } catch (Exception e) { |
| 1411 | + LOG.debug("Error checking containers for datanode {}: {}", dnInfo.getID(), e.getMessage()); |
| 1412 | + } |
| 1413 | + return false; |
| 1414 | + } |
| 1415 | + |
1364 | 1416 | /** |
1365 | 1417 | * Based on the current time and the last heartbeat, calculate the time difference |
1366 | 1418 | * and get a string of the relative value. E.g. "2s ago", "1m 2s ago", etc. |
|
0 commit comments