This is an automated email from the ASF dual-hosted git repository.
jt2594838 pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/dev/1.3 by this push:
new a2b32874e9e [To dev/1.3] Fix DataNode status handling for Pipe
receiver disk failures (#18484) (#18526)
a2b32874e9e is described below
commit a2b32874e9ec4f5727f5fd088fcb075e0ca87061
Author: Caideyipi <[email protected]>
AuthorDate: Wed Aug 26 14:53:20 2026 +0800
[To dev/1.3] Fix DataNode status handling for Pipe receiver disk failures
(#18484) (#18526)
Adapt the disk status handling and Pipe receiver folder allocation to the
1.3 storage-engine layout.
(cherry picked from commit 930e9bc0cf7ce0ab0984501aa1d973770f164b5f)
---
.../pipeconsensus/PipeConsensusReceiver.java | 2 +-
.../protocol/thrift/IoTDBDataNodeReceiver.java | 4 +-
.../impl/DataNodeInternalRPCServiceImpl.java | 28 +++---
.../storageengine/rescon/disk/FolderManager.java | 36 +++++---
.../rescon/disk/strategy/DirectoryStrategy.java | 15 ++-
.../DataNodeInternalRPCServiceImplDiskTest.java | 102 +++++++++++++++++++++
.../rescon/disk/FolderManagerTest.java | 76 +++++++++++++++
.../apache/iotdb/commons/conf/CommonConfig.java | 6 +-
.../iotdb/commons/conf/CommonConfigTest.java | 40 ++++++++
9 files changed, 275 insertions(+), 34 deletions(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/pipeconsensus/PipeConsensusReceiver.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/pipeconsensus/PipeConsensusReceiver.java
index dc48e634dbf..0bca71ede65 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/pipeconsensus/PipeConsensusReceiver.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/pipeconsensus/PipeConsensusReceiver.java
@@ -123,7 +123,7 @@ public class PipeConsensusReceiver {
try {
this.folderManager =
- new FolderManager(receiverBaseDirsName,
DirectoryStrategyType.SEQUENCE_STRATEGY);
+ new FolderManager(receiverBaseDirsName,
DirectoryStrategyType.SEQUENCE_STRATEGY, false);
} catch (Exception e) {
LOGGER.error(
"Fail to create pipeConsensus receiver file folders allocation
strategy because all disks of folders are full.",
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
index 3fbda2083dd..be7bc255e23 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
@@ -176,7 +176,9 @@ public class IoTDBDataNodeReceiver extends
IoTDBFileReceiver {
try {
folderManager =
new FolderManager(
- Arrays.asList(RECEIVER_FILE_BASE_DIRS),
DirectoryStrategyType.SEQUENCE_STRATEGY);
+ Arrays.asList(RECEIVER_FILE_BASE_DIRS),
+ DirectoryStrategyType.SEQUENCE_STRATEGY,
+ false);
} catch (final DiskSpaceInsufficientException e) {
LOGGER.error(
"Fail to create pipe receiver file folders allocation strategy
because all disks of folders are full.",
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
index 9edb75c641c..3c24909aee2 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
@@ -164,6 +164,7 @@ import org.apache.iotdb.db.trigger.executor.TriggerExecutor;
import org.apache.iotdb.db.trigger.executor.TriggerFireResult;
import org.apache.iotdb.db.trigger.service.TriggerManagementService;
import org.apache.iotdb.db.utils.SetThreadName;
+import org.apache.iotdb.metrics.metricsets.system.SystemMetrics;
import org.apache.iotdb.metrics.type.AutoGauge;
import org.apache.iotdb.metrics.utils.MetricLevel;
import org.apache.iotdb.metrics.utils.SystemMetric;
@@ -333,6 +334,8 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
private final CommonConfig commonConfig =
CommonDescriptor.getInstance().getConfig();
+ private final SystemMetrics systemMetrics;
+
private final ExecutorService schemaExecutor =
new WrappedThreadPoolExecutor(
0,
@@ -348,7 +351,12 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
private static final String SYSTEM = "system";
public DataNodeInternalRPCServiceImpl() {
+ this(SystemMetrics.getInstance());
+ }
+
+ DataNodeInternalRPCServiceImpl(SystemMetrics systemMetrics) {
super();
+ this.systemMetrics = systemMetrics;
partitionFetcher = ClusterPartitionFetcher.getInstance();
schemaFetcher = ClusterSchemaFetcher.getInstance();
}
@@ -1852,23 +1860,9 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
return result;
}
- private void sampleDiskLoad(TLoadSample loadSample) {
- double availableDisk =
- MetricService.getInstance()
- .getAutoGauge(
- SystemMetric.SYS_DISK_AVAILABLE_SPACE.toString(),
- MetricLevel.CORE,
- Tag.NAME.toString(),
- SYSTEM)
- .getValue();
- double totalDisk =
- MetricService.getInstance()
- .getAutoGauge(
- SystemMetric.SYS_DISK_TOTAL_SPACE.toString(),
- MetricLevel.CORE,
- Tag.NAME.toString(),
- SYSTEM)
- .getValue();
+ void sampleDiskLoad(TLoadSample loadSample) {
+ double availableDisk = systemMetrics.getSystemDiskAvailableSpace();
+ double totalDisk = systemMetrics.getSystemDiskTotalSpace();
if (availableDisk != 0 && totalDisk != 0) {
double freeDiskRatio = availableDisk / totalDisk;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManager.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManager.java
index 9315c63cd55..a3cc260d453 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManager.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManager.java
@@ -40,10 +40,18 @@ public class FolderManager {
private final List<String> folders;
private final DirectoryStrategy selectStrategy;
+ private final boolean changeSystemStatusToReadOnly;
public FolderManager(List<String> folders, DirectoryStrategyType type)
throws DiskSpaceInsufficientException {
+ this(folders, type, true);
+ }
+
+ public FolderManager(
+ List<String> folders, DirectoryStrategyType type, boolean
changeSystemStatusToReadOnly)
+ throws DiskSpaceInsufficientException {
this.folders = folders;
+ this.changeSystemStatusToReadOnly = changeSystemStatusToReadOnly;
switch (type) {
case SEQUENCE_STRATEGY:
this.selectStrategy = new SequenceStrategy();
@@ -60,15 +68,11 @@ public class FolderManager {
default:
throw new RuntimeException();
}
+
this.selectStrategy.setChangeSystemStatusToReadOnly(changeSystemStatusToReadOnly);
try {
this.selectStrategy.setFolders(folders);
} catch (DiskSpaceInsufficientException e) {
- if (LoggerPeriodicalLogReducer.shouldLog(
- "All folders are full, change system mode to read-only.")) {
- logger.error("All folders are full, change system mode to read-only.",
e);
- }
-
CommonDescriptor.getInstance().getConfig().setNodeStatus(NodeStatus.ReadOnly);
-
CommonDescriptor.getInstance().getConfig().setStatusReason(NodeStatus.DISK_FULL);
+ changeToReadOnlyIfDiskFull(e);
throw e;
}
}
@@ -77,16 +81,24 @@ public class FolderManager {
try {
return folders.get(selectStrategy.nextFolderIndex());
} catch (DiskSpaceInsufficientException e) {
- if (LoggerPeriodicalLogReducer.shouldLog(
- "All folders are full, change system mode to read-only.")) {
- logger.error("All folders are full, change system mode to read-only.",
e);
- }
-
CommonDescriptor.getInstance().getConfig().setNodeStatus(NodeStatus.ReadOnly);
-
CommonDescriptor.getInstance().getConfig().setStatusReason(NodeStatus.DISK_FULL);
+ changeToReadOnlyIfDiskFull(e);
throw e;
}
}
+ private void changeToReadOnlyIfDiskFull(DiskSpaceInsufficientException e) {
+ if (!changeSystemStatusToReadOnly) {
+ return;
+ }
+
+ if (LoggerPeriodicalLogReducer.shouldLog(
+ "All folders are full, change system mode to read-only.")) {
+ logger.error("All folders are full, change system mode to read-only.",
e);
+ }
+
CommonDescriptor.getInstance().getConfig().setNodeStatus(NodeStatus.ReadOnly);
+
CommonDescriptor.getInstance().getConfig().setStatusReason(NodeStatus.DISK_FULL);
+ }
+
public List<String> getFolders() {
return folders;
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/DirectoryStrategy.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/DirectoryStrategy.java
index 4cf7764183d..68a15e15af7 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/DirectoryStrategy.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/rescon/disk/strategy/DirectoryStrategy.java
@@ -20,6 +20,7 @@ package
org.apache.iotdb.db.storageengine.rescon.disk.strategy;
import org.apache.iotdb.commons.cluster.NodeStatus;
import org.apache.iotdb.commons.conf.CommonDescriptor;
+import org.apache.iotdb.commons.log.LoggerPeriodicalLogReducer;
import org.apache.iotdb.commons.utils.JVMCommonUtils;
import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
@@ -40,6 +41,12 @@ public abstract class DirectoryStrategy {
/** All the folders of data files, should be init once the subclass is
created. */
List<String> folders = new ArrayList<>();
+ private boolean changeSystemStatusToReadOnly = true;
+
+ public void setChangeSystemStatusToReadOnly(boolean
changeSystemStatusToReadOnly) {
+ this.changeSystemStatusToReadOnly = changeSystemStatusToReadOnly;
+ }
+
/**
* To init folders. Do not recommend to overwrite. This method guarantees
that at least one folder
* has available space.
@@ -55,8 +62,12 @@ public abstract class DirectoryStrategy {
}
}
if (!hasSpace) {
- LOGGER.error("Disk space is insufficient, change system mode to
read-only");
-
CommonDescriptor.getInstance().getConfig().setNodeStatus(NodeStatus.ReadOnly);
+ if (changeSystemStatusToReadOnly) {
+ LOGGER.error("Disk space is insufficient, change system mode to
read-only");
+
CommonDescriptor.getInstance().getConfig().setNodeStatus(NodeStatus.ReadOnly);
+ } else if (LoggerPeriodicalLogReducer.shouldLog("Disk space is
insufficient.")) {
+ LOGGER.error("Disk space is insufficient.");
+ }
throw new DiskSpaceInsufficientException(folders);
}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImplDiskTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImplDiskTest.java
new file mode 100644
index 00000000000..4dc1b46165e
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImplDiskTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.protocol.thrift.impl;
+
+import org.apache.iotdb.common.rpc.thrift.TLoadSample;
+import org.apache.iotdb.commons.cluster.NodeStatus;
+import org.apache.iotdb.commons.conf.CommonConfig;
+import org.apache.iotdb.commons.conf.CommonDescriptor;
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.metrics.metricsets.system.SystemMetrics;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DataNodeInternalRPCServiceImplDiskTest {
+
+ private final CommonConfig commonConfig =
CommonDescriptor.getInstance().getConfig();
+ private final IoTDBConfig dataNodeConfig =
IoTDBDescriptor.getInstance().getConfig();
+ private NodeStatus originalStatus;
+ private String originalStatusReason;
+ private double originalDiskSpaceWarningThreshold;
+ private int originalDataNodeId;
+
+ @Before
+ public void setUp() {
+ originalStatus = commonConfig.getNodeStatus();
+ originalStatusReason = commonConfig.getStatusReason();
+ originalDiskSpaceWarningThreshold =
commonConfig.getDiskSpaceWarningThreshold();
+ originalDataNodeId = dataNodeConfig.getDataNodeId();
+
+ dataNodeConfig.setDataNodeId(0);
+ commonConfig.setNodeStatus(NodeStatus.Running);
+ commonConfig.setStatusReason(null);
+ commonConfig.setDiskSpaceWarningThreshold(0.05);
+ commonConfig.setNodeStatus(NodeStatus.ReadOnly);
+ commonConfig.setStatusReason(NodeStatus.DISK_FULL);
+ }
+
+ @After
+ public void tearDown() {
+ commonConfig.setNodeStatus(originalStatus);
+ commonConfig.setStatusReason(originalStatusReason);
+
commonConfig.setDiskSpaceWarningThreshold(originalDiskSpaceWarningThreshold);
+ dataNodeConfig.setDataNodeId(originalDataNodeId);
+ }
+
+ @Test
+ public void testRunningRecoveryUsesAggregateDiskRatio() {
+ SystemMetrics systemMetrics = mock(SystemMetrics.class);
+ when(systemMetrics.getSystemDiskAvailableSpace()).thenReturn(104L);
+ when(systemMetrics.getSystemDiskTotalSpace()).thenReturn(200L);
+
+ DataNodeInternalRPCServiceImpl service = new
DataNodeInternalRPCServiceImpl(systemMetrics);
+ TLoadSample loadSample = new TLoadSample();
+
+ service.sampleDiskLoad(loadSample);
+
+ Assert.assertEquals(NodeStatus.Running, commonConfig.getNodeStatus());
+ Assert.assertNull(commonConfig.getStatusReason());
+ Assert.assertEquals(104.0, loadSample.getFreeDiskSpace(), 0.0);
+ Assert.assertEquals(0.48, loadSample.getDiskUsageRate(), 1e-10);
+ }
+
+ @Test
+ public void testStorageEngineDiskAggregateStillEntersReadOnly() {
+ SystemMetrics systemMetrics = mock(SystemMetrics.class);
+ when(systemMetrics.getSystemDiskAvailableSpace()).thenReturn(4L);
+ when(systemMetrics.getSystemDiskTotalSpace()).thenReturn(100L);
+
+ commonConfig.setNodeStatus(NodeStatus.Running);
+ commonConfig.setStatusReason(null);
+ DataNodeInternalRPCServiceImpl service = new
DataNodeInternalRPCServiceImpl(systemMetrics);
+
+ service.sampleDiskLoad(new TLoadSample());
+
+ Assert.assertEquals(NodeStatus.ReadOnly, commonConfig.getNodeStatus());
+ Assert.assertEquals(NodeStatus.DISK_FULL, commonConfig.getStatusReason());
+ }
+}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManagerTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManagerTest.java
new file mode 100644
index 00000000000..470d8a5e289
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/rescon/disk/FolderManagerTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.storageengine.rescon.disk;
+
+import org.apache.iotdb.commons.cluster.NodeStatus;
+import org.apache.iotdb.commons.conf.CommonConfig;
+import org.apache.iotdb.commons.conf.CommonDescriptor;
+import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
+import
org.apache.iotdb.db.storageengine.rescon.disk.strategy.DirectoryStrategyType;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collections;
+
+public class FolderManagerTest {
+
+ private final CommonConfig commonConfig =
CommonDescriptor.getInstance().getConfig();
+ private NodeStatus originalStatus;
+ private String originalStatusReason;
+
+ @Before
+ public void setUp() {
+ originalStatus = commonConfig.getNodeStatus();
+ originalStatusReason = commonConfig.getStatusReason();
+ commonConfig.setNodeStatus(NodeStatus.Running);
+ commonConfig.setStatusReason(null);
+ }
+
+ @After
+ public void tearDown() {
+ commonConfig.setNodeStatus(originalStatus);
+ commonConfig.setStatusReason(originalStatusReason);
+ }
+
+ @Test
+ public void testSkipNodeStatusChangeWhenDiskFull() {
+ try {
+ new FolderManager(Collections.emptyList(),
DirectoryStrategyType.SEQUENCE_STRATEGY, false);
+ Assert.fail("Expected DiskSpaceInsufficientException");
+ } catch (DiskSpaceInsufficientException e) {
+ Assert.assertEquals(NodeStatus.Running, commonConfig.getNodeStatus());
+ Assert.assertNull(commonConfig.getStatusReason());
+ }
+ }
+
+ @Test
+ public void testChangeNodeStatusWhenDiskFullByDefault() {
+ try {
+ new FolderManager(Collections.emptyList(),
DirectoryStrategyType.SEQUENCE_STRATEGY);
+ Assert.fail("Expected DiskSpaceInsufficientException");
+ } catch (DiskSpaceInsufficientException e) {
+ Assert.assertEquals(NodeStatus.ReadOnly, commonConfig.getNodeStatus());
+ Assert.assertEquals(NodeStatus.DISK_FULL,
commonConfig.getStatusReason());
+ }
+ }
+}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
index de7e476c935..b0ad9b66d3c 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
@@ -688,7 +688,11 @@ public class CommonConfig {
return status;
}
- public void setNodeStatus(NodeStatus newStatus) {
+ public synchronized void setNodeStatus(NodeStatus newStatus) {
+ if (status == newStatus) {
+ return;
+ }
+
logger.info("Set system mode from {} to {}.", status, newStatus);
this.status = newStatus;
this.statusReason = null;
diff --git
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/conf/CommonConfigTest.java
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/conf/CommonConfigTest.java
new file mode 100644
index 00000000000..ac3a001175a
--- /dev/null
+++
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/conf/CommonConfigTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.commons.conf;
+
+import org.apache.iotdb.commons.cluster.NodeStatus;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CommonConfigTest {
+
+ @Test
+ public void testSameNodeStatusDoesNotClearStatusReason() {
+ CommonConfig config = new CommonConfig();
+ config.setNodeStatus(NodeStatus.ReadOnly);
+ config.setStatusReason(NodeStatus.DISK_FULL);
+
+ config.setNodeStatus(NodeStatus.ReadOnly);
+
+ Assert.assertEquals(NodeStatus.ReadOnly, config.getNodeStatus());
+ Assert.assertEquals(NodeStatus.DISK_FULL, config.getStatusReason());
+ }
+}