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     */
018    package org.apache.hadoop.ha;
019    
020    import java.io.IOException;
021    import java.net.InetSocketAddress;
022    import java.util.Map;
023    
024    import javax.net.SocketFactory;
025    
026    import org.apache.hadoop.classification.InterfaceAudience;
027    import org.apache.hadoop.classification.InterfaceStability;
028    import org.apache.hadoop.conf.Configuration;
029    import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
030    import org.apache.hadoop.ha.protocolPB.HAServiceProtocolClientSideTranslatorPB;
031    import org.apache.hadoop.ha.protocolPB.ZKFCProtocolClientSideTranslatorPB;
032    import org.apache.hadoop.net.NetUtils;
033    
034    import 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
041    public 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       * @return the IPC address of the ZKFC on the target node
054       */
055      public abstract InetSocketAddress getZKFCAddress();
056    
057      /**
058       * @return a Fencer implementation configured for this target node
059       */
060      public abstract NodeFencer getFencer();
061      
062      /**
063       * @throws BadFencingConfigurationException if the fencing configuration
064       * appears to be invalid. This is divorced from the above
065       * {@link #getFencer()} method so that the configuration can be checked
066       * during the pre-flight phase of failover.
067       */
068      public abstract void checkFencingConfigured()
069          throws BadFencingConfigurationException;
070      
071      /**
072       * @return a proxy to connect to the target HA Service.
073       */
074      public HAServiceProtocol getProxy(Configuration conf, int timeoutMs)
075          throws IOException {
076        Configuration confCopy = new Configuration(conf);
077        // Lower the timeout so we quickly fail to connect
078        confCopy.setInt(CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 1);
079        SocketFactory factory = NetUtils.getDefaultSocketFactory(confCopy);
080        return new HAServiceProtocolClientSideTranslatorPB(
081            getAddress(),
082            confCopy, factory, timeoutMs);
083      }
084      
085      /**
086       * @return a proxy to the ZKFC which is associated with this HA service.
087       */
088      public ZKFCProtocol getZKFCProxy(Configuration conf, int timeoutMs)
089          throws IOException {
090        Configuration confCopy = new Configuration(conf);
091        // Lower the timeout so we quickly fail to connect
092        confCopy.setInt(CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 1);
093        SocketFactory factory = NetUtils.getDefaultSocketFactory(confCopy);
094        return new ZKFCProtocolClientSideTranslatorPB(
095            getZKFCAddress(),
096            confCopy, factory, timeoutMs);
097      }
098      
099      public final Map<String, String> getFencingParameters() {
100        Map<String, String> ret = Maps.newHashMap();
101        addFencingParameters(ret);
102        return ret;
103      }
104      
105      /**
106       * Hook to allow subclasses to add any parameters they would like to
107       * expose to fencing implementations/scripts. Fencing methods are free
108       * to use this map as they see fit -- notably, the shell script
109       * implementation takes each entry, prepends 'target_', substitutes
110       * '_' for '.', and adds it to the environment of the script.
111       *
112       * Subclass implementations should be sure to delegate to the superclass
113       * implementation as well as adding their own keys.
114       *
115       * @param ret map which can be mutated to pass parameters to the fencer
116       */
117      protected void addFencingParameters(Map<String, String> ret) {
118        ret.put(ADDRESS_SUBST_KEY, String.valueOf(getAddress()));
119        ret.put(HOST_SUBST_KEY, getAddress().getHostName());
120        ret.put(PORT_SUBST_KEY, String.valueOf(getAddress().getPort()));
121      }
122    
123      /**
124       * @return true if auto failover should be considered enabled
125       */
126      public boolean isAutoFailoverEnabled() {
127        return false;
128      }
129    }