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.master; 019 020import static org.junit.jupiter.api.Assertions.fail; 021import static org.mockito.Mockito.mock; 022import static org.mockito.Mockito.when; 023 024import java.net.InetAddress; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.ClockOutOfSyncException; 027import org.apache.hadoop.hbase.HBaseConfiguration; 028import org.apache.hadoop.hbase.master.assignment.AssignmentManager; 029import org.apache.hadoop.hbase.master.assignment.RegionStates; 030import org.apache.hadoop.hbase.testclassification.MasterTests; 031import org.apache.hadoop.hbase.testclassification.SmallTests; 032import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 033import org.junit.jupiter.api.Tag; 034import org.junit.jupiter.api.Test; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest; 039 040@Tag(MasterTests.TAG) 041@Tag(SmallTests.TAG) 042public class TestClockSkewDetection { 043 044 private static final Logger LOG = LoggerFactory.getLogger(TestClockSkewDetection.class); 045 046 private static final class DummyMasterServices extends MockNoopMasterServices { 047 048 private final AssignmentManager am; 049 050 public DummyMasterServices(Configuration conf) { 051 super(conf); 052 am = mock(AssignmentManager.class); 053 RegionStates rss = mock(RegionStates.class); 054 when(am.getRegionStates()).thenReturn(rss); 055 } 056 057 @Override 058 public AssignmentManager getAssignmentManager() { 059 return am; 060 } 061 } 062 063 @Test 064 public void testClockSkewDetection() throws Exception { 065 final Configuration conf = HBaseConfiguration.create(); 066 ServerManager sm = 067 new ServerManager(new DummyMasterServices(conf), new DummyRegionServerList()); 068 069 LOG.debug("regionServerStartup 1"); 070 InetAddress ia1 = InetAddress.getLocalHost(); 071 RegionServerStartupRequest.Builder request = RegionServerStartupRequest.newBuilder(); 072 request.setPort(1234); 073 request.setServerStartCode(-1); 074 request.setServerCurrentTime(EnvironmentEdgeManager.currentTime()); 075 sm.regionServerStartup(request.build(), 0, "0.0.0", ia1); 076 077 final Configuration c = HBaseConfiguration.create(); 078 long maxSkew = c.getLong("hbase.master.maxclockskew", 30000); 079 long warningSkew = c.getLong("hbase.master.warningclockskew", 1000); 080 081 try { 082 // Master Time > Region Server Time 083 LOG.debug("Test: Master Time > Region Server Time"); 084 LOG.debug("regionServerStartup 2"); 085 InetAddress ia2 = InetAddress.getLocalHost(); 086 request = RegionServerStartupRequest.newBuilder(); 087 request.setPort(1235); 088 request.setServerStartCode(-1); 089 request.setServerCurrentTime(EnvironmentEdgeManager.currentTime() - maxSkew * 2); 090 sm.regionServerStartup(request.build(), 0, "0.0.0", ia2); 091 fail("HMaster should have thrown a ClockOutOfSyncException but didn't."); 092 } catch (ClockOutOfSyncException e) { 093 // we want an exception 094 LOG.info("Received expected exception: " + e); 095 } 096 097 try { 098 // Master Time < Region Server Time 099 LOG.debug("Test: Master Time < Region Server Time"); 100 LOG.debug("regionServerStartup 3"); 101 InetAddress ia3 = InetAddress.getLocalHost(); 102 request = RegionServerStartupRequest.newBuilder(); 103 request.setPort(1236); 104 request.setServerStartCode(-1); 105 request.setServerCurrentTime(EnvironmentEdgeManager.currentTime() + maxSkew * 2); 106 sm.regionServerStartup(request.build(), 0, "0.0.0", ia3); 107 fail("HMaster should have thrown a ClockOutOfSyncException but didn't."); 108 } catch (ClockOutOfSyncException e) { 109 // we want an exception 110 LOG.info("Received expected exception: " + e); 111 } 112 113 // make sure values above warning threshold but below max threshold don't kill 114 LOG.debug("regionServerStartup 4"); 115 InetAddress ia4 = InetAddress.getLocalHost(); 116 request = RegionServerStartupRequest.newBuilder(); 117 request.setPort(1237); 118 request.setServerStartCode(-1); 119 request.setServerCurrentTime(EnvironmentEdgeManager.currentTime() - warningSkew * 2); 120 sm.regionServerStartup(request.build(), 0, "0.0.0", ia4); 121 122 // make sure values above warning threshold but below max threshold don't kill 123 LOG.debug("regionServerStartup 5"); 124 InetAddress ia5 = InetAddress.getLocalHost(); 125 request = RegionServerStartupRequest.newBuilder(); 126 request.setPort(1238); 127 request.setServerStartCode(-1); 128 request.setServerCurrentTime(EnvironmentEdgeManager.currentTime() + warningSkew * 2); 129 sm.regionServerStartup(request.build(), 0, "0.0.0", ia5); 130 } 131}