001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import java.io.IOException; 021import java.nio.file.Files; 022import java.nio.file.Path; 023import java.nio.file.Paths; 024import java.nio.file.StandardCopyOption; 025import org.apache.hadoop.hbase.HBaseTestingUtil; 026import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030/** 031 * Base class to test Configuration Update logic. It wraps up things needed to test configuration 032 * change and provides utility methods for test cluster setup, updating/restoring configuration 033 * file. 034 */ 035public abstract class AbstractTestUpdateConfiguration { 036 private static final Logger LOG = LoggerFactory.getLogger(AbstractTestUpdateConfiguration.class); 037 038 private static final String SERVER_CONFIG = "hbase-site.xml"; 039 private static final String OVERRIDE_SERVER_CONFIG = "override-hbase-site.xml"; 040 private static final String BACKUP_SERVER_CONFIG = "backup-hbase-site.xml"; 041 042 private static Path configFileUnderTestDataDir; 043 private static Path overrideConfigFileUnderTestDataDir; 044 private static Path backupConfigFileUnderTestDataDir; 045 046 protected static void setUpConfigurationFiles(final HBaseTestingUtil testUtil) throws Exception { 047 // Before this change, the test will update hbase-site.xml under target/test-classes and 048 // trigger a config reload. Since target/test-classes/hbase-site.xml is being used by 049 // other testing cases at the same time, this update will break other testing cases so it will 050 // be flakey in nature. 051 // To avoid this, the change is to make target/test-classes/hbase-site.xml immutable. A new 052 // hbase-site.xml will be created under its test data directory, i.e, 053 // hbase-server/target/test-data/UUID, this new file will be added as a resource for the 054 // config, new update will be applied to this new file and only visible to this specific test 055 // case. The target/test-classes/hbase-site.xml will not be changed during the test. 056 057 String absoluteDataPath = testUtil.getDataTestDir().toString(); 058 059 // Create test-data directories. 060 Files.createDirectories(Paths.get(absoluteDataPath)); 061 062 // Copy hbase-site.xml from target/test-class to target/test-data/UUID directory. 063 Path configFile = Paths.get("target", "test-classes", SERVER_CONFIG); 064 configFileUnderTestDataDir = Paths.get(absoluteDataPath, SERVER_CONFIG); 065 Files.copy(configFile, configFileUnderTestDataDir); 066 067 // Copy override config file overrider-hbase-site.xml from target/test-class to 068 // target/test-data/UUID directory. 069 Path overrideConfigFile = Paths.get("target", "test-classes", OVERRIDE_SERVER_CONFIG); 070 overrideConfigFileUnderTestDataDir = Paths.get(absoluteDataPath, OVERRIDE_SERVER_CONFIG); 071 Files.copy(overrideConfigFile, overrideConfigFileUnderTestDataDir); 072 073 backupConfigFileUnderTestDataDir = Paths.get(absoluteDataPath, BACKUP_SERVER_CONFIG); 074 075 // Add the new custom config file to Configuration 076 testUtil.getConfiguration().addResource(testUtil.getDataTestDir(SERVER_CONFIG)); 077 } 078 079 protected static void addResourceToRegionServerConfiguration(final HBaseTestingUtil testUtil) { 080 // When RegionServer is created in MiniHBaseCluster, it uses HBaseConfiguration.create(conf) of 081 // the master Configuration. The create() just copies config params over, it does not do 082 // a clone for a historic reason. Properties such as resources are lost during this process. 083 // Exposing a new method in HBaseConfiguration causes confusion. Instead, the new hbase-site.xml 084 // under test-data directory is added to RegionServer's configuration as a workaround. 085 for (RegionServerThread rsThread : testUtil.getMiniHBaseCluster().getRegionServerThreads()) { 086 rsThread.getRegionServer().getConfiguration() 087 .addResource(testUtil.getDataTestDir(SERVER_CONFIG)); 088 } 089 } 090 091 /** 092 * Replace the hbase-site.xml file under this test's data directory with the content of the 093 * override-hbase-site.xml file. Stashes the current existing file so that it can be restored 094 * using {@link #restoreHBaseSiteXML()}. 095 * @throws IOException if an I/O error occurs 096 */ 097 protected final void replaceHBaseSiteXML() throws IOException { 098 LOG.info("Replace hbase config {} with {}", configFileUnderTestDataDir, 099 overrideConfigFileUnderTestDataDir); 100 // make a backup of hbase-site.xml 101 Files.copy(configFileUnderTestDataDir, backupConfigFileUnderTestDataDir, 102 StandardCopyOption.REPLACE_EXISTING); 103 // update hbase-site.xml by overwriting it 104 Files.copy(overrideConfigFileUnderTestDataDir, configFileUnderTestDataDir, 105 StandardCopyOption.REPLACE_EXISTING); 106 } 107 108 /** 109 * Restores the hbase-site.xml file that was stashed by a previous call to 110 * {@link #replaceHBaseSiteXML()}. 111 * @throws IOException if an I/O error occurs 112 */ 113 protected final void restoreHBaseSiteXML() throws IOException { 114 LOG.info("Restore hbase config {} with {}", configFileUnderTestDataDir, 115 backupConfigFileUnderTestDataDir); 116 // restore hbase-site.xml 117 Files.copy(backupConfigFileUnderTestDataDir, configFileUnderTestDataDir, 118 StandardCopyOption.REPLACE_EXISTING); 119 } 120}