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.ha; 019 020import java.io.IOException; 021import java.net.InetSocketAddress; 022import java.util.Map; 023 024import javax.net.SocketFactory; 025 026import org.apache.hadoop.classification.InterfaceAudience; 027import org.apache.hadoop.classification.InterfaceStability; 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.fs.CommonConfigurationKeysPublic; 030import org.apache.hadoop.ha.protocolPB.HAServiceProtocolClientSideTranslatorPB; 031import org.apache.hadoop.ha.protocolPB.ZKFCProtocolClientSideTranslatorPB; 032import org.apache.hadoop.net.NetUtils; 033 034import com.google.common.collect.Maps; 035 036/** 037 * Represents a target of the client side HA administration commands. 038 */ 039@InterfaceAudience.Public 040@InterfaceStability.Evolving 041public abstract class HAServiceTarget { 042 043 private static final String HOST_SUBST_KEY = "host"; 044 private static final String PORT_SUBST_KEY = "port"; 045 private static final String ADDRESS_SUBST_KEY = "address"; 046 047 /** 048 * @return the IPC address of the target node. 049 */ 050 public abstract InetSocketAddress getAddress(); 051 052 /** 053 * Returns an optional separate RPC server address for health checks at the 054 * target node. If defined, then this address is used by the health monitor 055 * for the {@link HAServiceProtocol#monitorHealth()} and 056 * {@link HAServiceProtocol#getServiceStatus()} calls. This can be useful for 057 * separating out these calls onto separate RPC handlers to protect against 058 * resource exhaustion in the main RPC handler pool. If null (which is the 059 * default implementation), then all RPC calls go to the address defined by 060 * {@link #getAddress()}. 061 * 062 * @return IPC address of the lifeline RPC server on the target node, or null 063 * if no lifeline RPC server is used 064 */ 065 public InetSocketAddress getHealthMonitorAddress() { 066 return null; 067 } 068 069 /** 070 * @return the IPC address of the ZKFC on the target node 071 */ 072 public abstract InetSocketAddress getZKFCAddress(); 073 074 /** 075 * @return a Fencer implementation configured for this target node 076 */ 077 public abstract NodeFencer getFencer(); 078 079 /** 080 * @throws BadFencingConfigurationException if the fencing configuration 081 * appears to be invalid. This is divorced from the above 082 * {@link #getFencer()} method so that the configuration can be checked 083 * during the pre-flight phase of failover. 084 */ 085 public abstract void checkFencingConfigured() 086 throws BadFencingConfigurationException; 087 088 /** 089 * @return a proxy to connect to the target HA Service. 090 */ 091 public HAServiceProtocol getProxy(Configuration conf, int timeoutMs) 092 throws IOException { 093 return getProxyForAddress(conf, timeoutMs, getAddress()); 094 } 095 096 /** 097 * Returns a proxy to connect to the target HA service for health monitoring. 098 * If {@link #getHealthMonitorAddress()} is implemented to return a non-null 099 * address, then this proxy will connect to that address. Otherwise, the 100 * returned proxy defaults to using {@link #getAddress()}, which means this 101 * method's behavior is identical to {@link #getProxy(Configuration, int)}. 102 * 103 * @param conf Configuration 104 * @param timeoutMs timeout in milliseconds 105 * @return a proxy to connect to the target HA service for health monitoring 106 * @throws IOException if there is an error 107 */ 108 public HAServiceProtocol getHealthMonitorProxy(Configuration conf, 109 int timeoutMs) throws IOException { 110 InetSocketAddress addr = getHealthMonitorAddress(); 111 if (addr == null) { 112 addr = getAddress(); 113 } 114 return getProxyForAddress(conf, timeoutMs, addr); 115 } 116 117 private HAServiceProtocol getProxyForAddress(Configuration conf, 118 int timeoutMs, InetSocketAddress addr) throws IOException { 119 Configuration confCopy = new Configuration(conf); 120 // Lower the timeout so we quickly fail to connect 121 confCopy.setInt( 122 CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 1); 123 SocketFactory factory = NetUtils.getDefaultSocketFactory(confCopy); 124 return new HAServiceProtocolClientSideTranslatorPB( 125 addr, 126 confCopy, factory, timeoutMs); 127 } 128 129 /** 130 * @return a proxy to the ZKFC which is associated with this HA service. 131 */ 132 public ZKFCProtocol getZKFCProxy(Configuration conf, int timeoutMs) 133 throws IOException { 134 Configuration confCopy = new Configuration(conf); 135 // Lower the timeout so we quickly fail to connect 136 confCopy.setInt(CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 1); 137 SocketFactory factory = NetUtils.getDefaultSocketFactory(confCopy); 138 return new ZKFCProtocolClientSideTranslatorPB( 139 getZKFCAddress(), 140 confCopy, factory, timeoutMs); 141 } 142 143 public final Map<String, String> getFencingParameters() { 144 Map<String, String> ret = Maps.newHashMap(); 145 addFencingParameters(ret); 146 return ret; 147 } 148 149 /** 150 * Hook to allow subclasses to add any parameters they would like to 151 * expose to fencing implementations/scripts. Fencing methods are free 152 * to use this map as they see fit -- notably, the shell script 153 * implementation takes each entry, prepends 'target_', substitutes 154 * '_' for '.', and adds it to the environment of the script. 155 * 156 * Subclass implementations should be sure to delegate to the superclass 157 * implementation as well as adding their own keys. 158 * 159 * @param ret map which can be mutated to pass parameters to the fencer 160 */ 161 protected void addFencingParameters(Map<String, String> ret) { 162 ret.put(ADDRESS_SUBST_KEY, String.valueOf(getAddress())); 163 ret.put(HOST_SUBST_KEY, getAddress().getHostName()); 164 ret.put(PORT_SUBST_KEY, String.valueOf(getAddress().getPort())); 165 } 166 167 /** 168 * @return true if auto failover should be considered enabled 169 */ 170 public boolean isAutoFailoverEnabled() { 171 return false; 172 } 173}