diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerData.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerData.java index ce0d17477ec7..f7175bd95ce5 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerData.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/ContainerData.java @@ -107,7 +107,7 @@ public abstract class ContainerData { private transient Optional lastDataScanTime = Optional.empty(); public static final Charset CHARSET_ENCODING = StandardCharsets.UTF_8; - private static final String DUMMY_CHECKSUM = new String(new byte[64], + public static final String DUMMY_CHECKSUM = new String(new byte[64], CHARSET_ENCODING); // Common Fields need to be stored in .container file. diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java index ce3d709e240f..35b2b7f16885 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueContainer.java @@ -659,7 +659,7 @@ public void importContainerData(KeyValueContainerData originalContainerData) } //fill in memory stat counter (keycount, byte usage) - KeyValueContainerUtil.parseKVContainerData(containerData, config); + KeyValueContainerUtil.parseKVContainerData(containerData, config, true); // rewriting the yaml file with new checksum calculation // restore imported container's state to the original state and flush the yaml file diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/TarContainerPacker.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/TarContainerPacker.java index 46a2a94975e0..bc12d8f067d4 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/TarContainerPacker.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/TarContainerPacker.java @@ -39,9 +39,13 @@ import org.apache.commons.compress.archivers.ArchiveOutputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.io.FileUtils; +import org.apache.hadoop.hdds.conf.ConfigurationSource; +import org.apache.hadoop.hdds.conf.OzoneConfiguration; import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerDataProto.State; import org.apache.hadoop.hdds.scm.container.common.helpers.StorageContainerException; import org.apache.hadoop.ozone.OzoneConsts; +import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils; +import org.apache.hadoop.ozone.container.common.impl.ContainerDataYaml; import org.apache.hadoop.ozone.container.common.interfaces.Container; import org.apache.hadoop.ozone.container.common.interfaces.ContainerPacker; import org.apache.hadoop.ozone.container.keyvalue.helpers.KeyValueContainerLocationUtil; @@ -62,6 +66,8 @@ public class TarContainerPacker private final CopyContainerCompression compression; + private final ConfigurationSource conf = new OzoneConfiguration(); + public TarContainerPacker(CopyContainerCompression compression) { this.compression = compression; } @@ -93,6 +99,15 @@ public byte[] unpackContainerData(Container container, Files.createDirectories(destContainerDir); } if (FileUtils.isEmptyDirectory(destContainerDir.toFile())) { + + //before state change to RECOVERING, we need to verify the checksum for untarContainerData. + if (descriptorFileContent != null) { + KeyValueContainerData untarContainerData = + (KeyValueContainerData) ContainerDataYaml + .readContainer(descriptorFileContent); + ContainerUtils.verifyChecksum(untarContainerData, conf); + } + // Before the atomic move, the destination dir is empty and doesn't have a metadata directory. // Writing the .container file will fail as the metadata dir doesn't exist. // So we instead save the container file to the containerUntarDir. diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerUtil.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerUtil.java index 080aa1182336..e927536ba6e0 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerUtil.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/helpers/KeyValueContainerUtil.java @@ -196,17 +196,33 @@ public static boolean noBlocksInContainer(DatanodeStore store, * Parse KeyValueContainerData and verify checksum. Set block related * metadata like block commit sequence id, block count, bytes used and * pending delete block count and delete transaction id. + * This method will verify checksum by default. * @param kvContainerData * @param config * @throws IOException */ public static void parseKVContainerData(KeyValueContainerData kvContainerData, ConfigurationSource config) throws IOException { + parseKVContainerData(kvContainerData, config, false); + } + + /** + * @param kvContainerData + * @param config + * @param skipVerifyChecksum checksum verification should be skipped if the state + * has changed to RECOVERING during container import, false otherwise + * @throws IOException + */ + public static void parseKVContainerData(KeyValueContainerData kvContainerData, + ConfigurationSource config, boolean skipVerifyChecksum) throws IOException { long containerID = kvContainerData.getContainerID(); // Verify Checksum - ContainerUtils.verifyChecksum(kvContainerData, config); + // skip verify checksum if the state has changed to RECOVERING during container import + if (!skipVerifyChecksum) { + ContainerUtils.verifyChecksum(kvContainerData, config); + } if (kvContainerData.getSchemaVersion() == null) { // If this container has not specified a schema version, it is in the old diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java index 51a949e496fc..216d748b4a41 100644 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java +++ b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueContainer.java @@ -387,6 +387,8 @@ public void testContainerImportExport(ContainerTestVersionInfo versionInfo) containerData.getMaxSize()); assertEquals(keyValueContainerData.getBytesUsed(), containerData.getBytesUsed()); + assertNotNull(containerData.getChecksum()); + assertNotEquals(containerData.DUMMY_CHECKSUM, container.getContainerData().getChecksum()); //Can't overwrite existing container KeyValueContainer finalContainer = container; diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestTarContainerPacker.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestTarContainerPacker.java index 564a24b299a4..7f5c4c6b27f1 100644 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestTarContainerPacker.java +++ b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestTarContainerPacker.java @@ -72,7 +72,7 @@ public class TestTarContainerPacker { private static final String TEST_CHUNK_FILE_CONTENT = "This is a chunk"; private static final String TEST_DESCRIPTOR_FILE_CONTENT = "!\n" + - "checksum: 2215d39f2ae1de89fec837d18dc6387d8cba22fb5943cf4616f80c4b34e2edfe\n" + + "checksum: 5e4bea7286f96d88a5b3a745011ff9e4281a5221bfe564413215cd85871dcfd8\n" + "chunksPath: target/test-dir/MiniOzoneClusterImpl-23c1bb30-d86a-4f79-88dc-574d8259a5b3/ozone-meta/datanode-4" + "/data-0/hdds/23c1bb30-d86a-4f79-88dc-574d8259a5b3/current/containerDir0/1/chunks\n" + "containerDBType: RocksDB\n" +