blob: c611ccb28e7e137ac2b67fdc5011914121c7b5b8 [file] [log] [blame]
/*
* 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.hadoop.ozone.container.common.impl;
import org.apache.hadoop.conf.StorageUnit;
import org.apache.hadoop.fs.FileSystemTestHelper;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
import org.apache.hadoop.ozone.container.common.helpers.ContainerUtils;
import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData;
import org.apache.hadoop.test.GenericTestUtils;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* This class tests create/read .container files.
*/
public class TestContainerDataYaml {
private static long testContainerID = 1234;
private static String testRoot = new FileSystemTestHelper().getTestRootDir();
private static final long MAXSIZE = (long) StorageUnit.GB.toBytes(5);
/**
* Creates a .container file. cleanup() should be called at the end of the
* test when container file is created.
*/
private File createContainerFile(long containerID) throws IOException {
new File(testRoot).mkdirs();
String containerPath = containerID + ".container";
KeyValueContainerData keyValueContainerData = new KeyValueContainerData(
containerID, MAXSIZE, UUID.randomUUID().toString(),
UUID.randomUUID().toString());
keyValueContainerData.setContainerDBType("RocksDB");
keyValueContainerData.setMetadataPath(testRoot);
keyValueContainerData.setChunksPath(testRoot);
File containerFile = new File(testRoot, containerPath);
// Create .container file with ContainerData
ContainerDataYaml.createContainerFile(ContainerProtos.ContainerType
.KeyValueContainer, keyValueContainerData, containerFile);
//Check .container file exists or not.
assertTrue(containerFile.exists());
return containerFile;
}
private void cleanup() {
FileUtil.fullyDelete(new File(testRoot));
}
@Test
public void testCreateContainerFile() throws IOException {
long containerID = testContainerID++;
File containerFile = createContainerFile(containerID);
// Read from .container file, and verify data.
KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml
.readContainerFile(containerFile);
assertEquals(containerID, kvData.getContainerID());
assertEquals(ContainerProtos.ContainerType.KeyValueContainer, kvData
.getContainerType());
assertEquals("RocksDB", kvData.getContainerDBType());
assertEquals(containerFile.getParent(), kvData.getMetadataPath());
assertEquals(containerFile.getParent(), kvData.getChunksPath());
assertEquals(ContainerProtos.ContainerDataProto.State.OPEN, kvData
.getState());
assertEquals(1, kvData.getLayOutVersion());
assertEquals(0, kvData.getMetadata().size());
assertEquals(MAXSIZE, kvData.getMaxSize());
// Update ContainerData.
kvData.addMetadata("VOLUME", "hdfs");
kvData.addMetadata("OWNER", "ozone");
kvData.setState(ContainerProtos.ContainerDataProto.State.CLOSED);
ContainerDataYaml.createContainerFile(ContainerProtos.ContainerType
.KeyValueContainer, kvData, containerFile);
// Reading newly updated data from .container file
kvData = (KeyValueContainerData) ContainerDataYaml.readContainerFile(
containerFile);
// verify data.
assertEquals(containerID, kvData.getContainerID());
assertEquals(ContainerProtos.ContainerType.KeyValueContainer, kvData
.getContainerType());
assertEquals("RocksDB", kvData.getContainerDBType());
assertEquals(containerFile.getParent(), kvData.getMetadataPath());
assertEquals(containerFile.getParent(), kvData.getChunksPath());
assertEquals(ContainerProtos.ContainerDataProto.State.CLOSED, kvData
.getState());
assertEquals(1, kvData.getLayOutVersion());
assertEquals(2, kvData.getMetadata().size());
assertEquals("hdfs", kvData.getMetadata().get("VOLUME"));
assertEquals("ozone", kvData.getMetadata().get("OWNER"));
assertEquals(MAXSIZE, kvData.getMaxSize());
}
@Test
public void testIncorrectContainerFile() throws IOException{
try {
String containerFile = "incorrect.container";
//Get file from resources folder
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(containerFile).getFile());
KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml
.readContainerFile(file);
fail("testIncorrectContainerFile failed");
} catch (IllegalArgumentException ex) {
GenericTestUtils.assertExceptionContains("No enum constant", ex);
}
}
@Test
public void testCheckBackWardCompatibilityOfContainerFile() throws
IOException {
// This test is for if we upgrade, and then .container files added by new
// server will have new fields added to .container file, after a while we
// decided to rollback. Then older ozone can read .container files
// created or not.
try {
String containerFile = "additionalfields.container";
//Get file from resources folder
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(containerFile).getFile());
KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml
.readContainerFile(file);
ContainerUtils.verifyChecksum(kvData);
//Checking the Container file data is consistent or not
assertEquals(ContainerProtos.ContainerDataProto.State.CLOSED, kvData
.getState());
assertEquals("RocksDB", kvData.getContainerDBType());
assertEquals(ContainerProtos.ContainerType.KeyValueContainer, kvData
.getContainerType());
assertEquals(9223372036854775807L, kvData.getContainerID());
assertEquals("/hdds/current/aed-fg4-hji-jkl/containerDir0/1", kvData
.getChunksPath());
assertEquals("/hdds/current/aed-fg4-hji-jkl/containerDir0/1", kvData
.getMetadataPath());
assertEquals(1, kvData.getLayOutVersion());
assertEquals(2, kvData.getMetadata().size());
} catch (Exception ex) {
ex.printStackTrace();
fail("testCheckBackWardCompatibilityOfContainerFile failed");
}
}
/**
* Test to verify {@link ContainerUtils#verifyChecksum(ContainerData)}.
*/
@Test
public void testChecksumInContainerFile() throws IOException {
long containerID = testContainerID++;
File containerFile = createContainerFile(containerID);
// Read from .container file, and verify data.
KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml
.readContainerFile(containerFile);
ContainerUtils.verifyChecksum(kvData);
cleanup();
}
/**
* Test to verify incorrect checksum is detected.
*/
@Test
public void testIncorrectChecksum() {
try {
String containerFile = "incorrect.checksum.container";
//Get file from resources folder
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(containerFile).getFile());
KeyValueContainerData kvData = (KeyValueContainerData) ContainerDataYaml
.readContainerFile(file);
ContainerUtils.verifyChecksum(kvData);
fail("testIncorrectChecksum failed");
} catch (Exception ex) {
GenericTestUtils.assertExceptionContains("Container checksum error for " +
"ContainerID:", ex);
}
}
}