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.net.NetUtils;
032    
033    import com.google.common.collect.Maps;
034    
035    /**
036     * Represents a target of the client side HA administration commands.
037     */
038    @InterfaceAudience.Public
039    @InterfaceStability.Evolving
040    public abstract class HAServiceTarget {
041    
042      private static final String HOST_SUBST_KEY = "host";
043      private static final String PORT_SUBST_KEY = "port";
044      private static final String ADDRESS_SUBST_KEY = "address";
045    
046      /**
047       * @return the IPC address of the target node.
048       */
049      public abstract InetSocketAddress getAddress();
050    
051      /**
052       * @return a Fencer implementation configured for this target node
053       */
054      public abstract NodeFencer getFencer();
055      
056      /**
057       * @throws BadFencingConfigurationException if the fencing configuration
058       * appears to be invalid. This is divorced from the above
059       * {@link #getFencer()} method so that the configuration can be checked
060       * during the pre-flight phase of failover.
061       */
062      public abstract void checkFencingConfigured()
063          throws BadFencingConfigurationException;
064      
065      /**
066       * @return a proxy to connect to the target HA Service.
067       */
068      public HAServiceProtocol getProxy(Configuration conf, int timeoutMs)
069          throws IOException {
070        Configuration confCopy = new Configuration(conf);
071        // Lower the timeout so we quickly fail to connect
072        confCopy.setInt(CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 1);
073        SocketFactory factory = NetUtils.getDefaultSocketFactory(confCopy);
074        return new HAServiceProtocolClientSideTranslatorPB(
075            getAddress(),
076            confCopy, factory, timeoutMs);
077      }
078      
079      public final Map<String, String> getFencingParameters() {
080        Map<String, String> ret = Maps.newHashMap();
081        addFencingParameters(ret);
082        return ret;
083      }
084      
085      /**
086       * Hook to allow subclasses to add any parameters they would like to
087       * expose to fencing implementations/scripts. Fencing methods are free
088       * to use this map as they see fit -- notably, the shell script
089       * implementation takes each entry, prepends 'target_', substitutes
090       * '_' for '.', and adds it to the environment of the script.
091       *
092       * Subclass implementations should be sure to delegate to the superclass
093       * implementation as well as adding their own keys.
094       *
095       * @param ret map which can be mutated to pass parameters to the fencer
096       */
097      protected void addFencingParameters(Map<String, String> ret) {
098        ret.put(ADDRESS_SUBST_KEY, String.valueOf(getAddress()));
099        ret.put(HOST_SUBST_KEY, getAddress().getHostName());
100        ret.put(PORT_SUBST_KEY, String.valueOf(getAddress().getPort()));
101      }
102    }