001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.apache.hadoop.hbase.client.replication;
020
021import java.io.Closeable;
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.HashMap;
026import java.util.List;
027import java.util.Map;
028import java.util.TreeMap;
029import java.util.regex.Pattern;
030import org.apache.hadoop.conf.Configuration;
031import org.apache.hadoop.hbase.HConstants;
032import org.apache.hadoop.hbase.ReplicationPeerNotFoundException;
033import org.apache.hadoop.hbase.TableName;
034import org.apache.hadoop.hbase.client.Admin;
035import org.apache.hadoop.hbase.client.Connection;
036import org.apache.hadoop.hbase.client.ConnectionFactory;
037import org.apache.hadoop.hbase.replication.ReplicationException;
038import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
039import org.apache.hadoop.hbase.replication.ReplicationPeerDescription;
040import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
041import org.apache.yetus.audience.InterfaceAudience;
042import org.slf4j.Logger;
043import org.slf4j.LoggerFactory;
044
045/**
046 * <p>
047 * This class provides the administrative interface to HBase cluster
048 * replication.
049 * </p>
050 * <p>
051 * Adding a new peer results in creating new outbound connections from every
052 * region server to a subset of region servers on the slave cluster. Each
053 * new stream of replication will start replicating from the beginning of the
054 * current WAL, meaning that edits from that past will be replicated.
055 * </p>
056 * <p>
057 * Removing a peer is a destructive and irreversible operation that stops
058 * all the replication streams for the given cluster and deletes the metadata
059 * used to keep track of the replication state.
060 * </p>
061 * <p>
062 * To see which commands are available in the shell, type
063 * <code>replication</code>.
064 * </p>
065 *
066 * @deprecated use {@link org.apache.hadoop.hbase.client.Admin} instead.
067 */
068@InterfaceAudience.Public
069@Deprecated
070public class ReplicationAdmin implements Closeable {
071  private static final Logger LOG = LoggerFactory.getLogger(ReplicationAdmin.class);
072
073  public static final String TNAME = "tableName";
074  public static final String CFNAME = "columnFamilyName";
075
076  // only Global for now, can add other type
077  // such as, 1) no global replication, or 2) the table is replicated to this cluster, etc.
078  public static final String REPLICATIONTYPE = "replicationType";
079  public static final String REPLICATIONGLOBAL = Integer
080      .toString(HConstants.REPLICATION_SCOPE_GLOBAL);
081
082  private final Connection connection;
083  private Admin admin;
084
085  /**
086   * Constructor that creates a connection to the local ZooKeeper ensemble.
087   * @param conf Configuration to use
088   * @throws IOException if an internal replication error occurs
089   * @throws RuntimeException if replication isn't enabled.
090   */
091  public ReplicationAdmin(Configuration conf) throws IOException {
092    this.connection = ConnectionFactory.createConnection(conf);
093    admin = connection.getAdmin();
094  }
095
096  /**
097   * Add a new remote slave cluster for replication.
098   * @param id a short name that identifies the cluster
099   * @param peerConfig configuration for the replication slave cluster
100   * @param tableCfs the table and column-family list which will be replicated for this peer.
101   * A map from tableName to column family names. An empty collection can be passed
102   * to indicate replicating all column families. Pass null for replicating all table and column
103   * families
104   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0,
105   * use {@link #addPeer(String, ReplicationPeerConfig)} instead.
106   */
107  @Deprecated
108  public void addPeer(String id, ReplicationPeerConfig peerConfig,
109      Map<TableName, ? extends Collection<String>> tableCfs) throws ReplicationException,
110      IOException {
111    if (tableCfs != null) {
112      peerConfig.setTableCFsMap(tableCfs);
113    }
114    this.admin.addReplicationPeer(id, peerConfig);
115  }
116
117  /**
118   * Add a new remote slave cluster for replication.
119   * @param id a short name that identifies the cluster
120   * @param peerConfig configuration for the replication slave cluster
121   * @deprecated use
122   *             {@link org.apache.hadoop.hbase.client.Admin#addReplicationPeer(String, ReplicationPeerConfig)}
123   *             instead
124   */
125  @Deprecated
126  public void addPeer(String id, ReplicationPeerConfig peerConfig) throws ReplicationException,
127      IOException {
128    this.admin.addReplicationPeer(id, peerConfig);
129  }
130
131  /**
132   *  @deprecated as release of 2.0.0, and it will be removed in 3.0.0
133   * */
134  @Deprecated
135  public static Map<TableName, List<String>> parseTableCFsFromConfig(String tableCFsConfig) {
136    return ReplicationPeerConfigUtil.parseTableCFsFromConfig(tableCFsConfig);
137  }
138
139  /**
140   * @deprecated use
141   *             {@link org.apache.hadoop.hbase.client.Admin#updateReplicationPeerConfig(String, ReplicationPeerConfig)}
142   *             instead
143   */
144  @Deprecated
145  public void updatePeerConfig(String id, ReplicationPeerConfig peerConfig) throws IOException {
146    this.admin.updateReplicationPeerConfig(id, peerConfig);
147  }
148
149  /**
150   * Removes a peer cluster and stops the replication to it.
151   * @param id a short name that identifies the cluster
152   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#removeReplicationPeer(String)} instead
153   */
154  @Deprecated
155  public void removePeer(String id) throws IOException {
156    this.admin.removeReplicationPeer(id);
157  }
158
159  /**
160   * Restart the replication stream to the specified peer.
161   * @param id a short name that identifies the cluster
162   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#enableReplicationPeer(String)}
163   *             instead
164   */
165  @Deprecated
166  public void enablePeer(String id) throws IOException {
167    this.admin.enableReplicationPeer(id);
168  }
169
170  /**
171   * Stop the replication stream to the specified peer.
172   * @param id a short name that identifies the cluster
173   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#disableReplicationPeer(String)}
174   *             instead
175   */
176  @Deprecated
177  public void disablePeer(String id) throws IOException {
178    this.admin.disableReplicationPeer(id);
179  }
180
181  /**
182   * Get the number of slave clusters the local cluster has.
183   * @return number of slave clusters
184   * @throws IOException
185   * @deprecated
186   */
187  @Deprecated
188  public int getPeersCount() throws IOException {
189    return this.admin.listReplicationPeers().size();
190  }
191
192  /**
193   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#listReplicationPeers()} instead
194   */
195  @Deprecated
196  public Map<String, ReplicationPeerConfig> listPeerConfigs() throws IOException {
197    List<ReplicationPeerDescription> peers = this.admin.listReplicationPeers();
198    Map<String, ReplicationPeerConfig> result = new TreeMap<>();
199    for (ReplicationPeerDescription peer : peers) {
200      result.put(peer.getPeerId(), peer.getPeerConfig());
201    }
202    return result;
203  }
204
205  /**
206   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#getReplicationPeerConfig(String)}
207   *             instead
208   */
209  @Deprecated
210  public ReplicationPeerConfig getPeerConfig(String id) throws IOException {
211    return admin.getReplicationPeerConfig(id);
212  }
213
214  /**
215   * Get the replicable table-cf config of the specified peer.
216   * @param id a short name that identifies the cluster
217   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0,
218   * use {@link #getPeerConfig(String)} instead.
219   * */
220  @Deprecated
221  public String getPeerTableCFs(String id) throws IOException {
222    ReplicationPeerConfig peerConfig = admin.getReplicationPeerConfig(id);
223    return ReplicationPeerConfigUtil.convertToString(peerConfig.getTableCFsMap());
224  }
225
226  /**
227   * Append the replicable table-cf config of the specified peer
228   * @param id a short that identifies the cluster
229   * @param tableCfs table-cfs config str
230   * @throws ReplicationException
231   * @throws IOException
232   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0,
233   * use {@link #appendPeerTableCFs(String, Map)} instead.
234   */
235  @Deprecated
236  public void appendPeerTableCFs(String id, String tableCfs) throws ReplicationException,
237      IOException {
238    appendPeerTableCFs(id, ReplicationPeerConfigUtil.parseTableCFsFromConfig(tableCfs));
239  }
240
241  /**
242   * Append the replicable table-cf config of the specified peer
243   * @param id a short that identifies the cluster
244   * @param tableCfs A map from tableName to column family names
245   * @throws ReplicationException
246   * @throws IOException
247   */
248  @Deprecated
249  public void appendPeerTableCFs(String id, Map<TableName, ? extends Collection<String>> tableCfs)
250      throws ReplicationException, IOException {
251    this.admin.appendReplicationPeerTableCFs(id, copyTableCFs(tableCfs));
252  }
253
254  /**
255   * Remove some table-cfs from table-cfs config of the specified peer
256   * @param id a short name that identifies the cluster
257   * @param tableCf table-cfs config str
258   * @throws ReplicationException
259   * @throws IOException
260   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0,
261   * use {@link #removePeerTableCFs(String, Map)} instead.
262   */
263  @Deprecated
264  public void removePeerTableCFs(String id, String tableCf) throws ReplicationException,
265      IOException {
266    removePeerTableCFs(id, ReplicationPeerConfigUtil.parseTableCFsFromConfig(tableCf));
267  }
268
269  /**
270   * Remove some table-cfs from config of the specified peer
271   * @param id a short name that identifies the cluster
272   * @param tableCfs A map from tableName to column family names
273   * @throws ReplicationException
274   * @throws IOException
275   */
276  @Deprecated
277  public void removePeerTableCFs(String id, Map<TableName, ? extends Collection<String>> tableCfs)
278      throws ReplicationException, IOException {
279    this.admin.removeReplicationPeerTableCFs(id, copyTableCFs(tableCfs));
280  }
281
282  private Map<TableName, List<String>>
283      copyTableCFs(Map<TableName, ? extends Collection<String>> tableCfs) {
284    Map<TableName, List<String>> newTableCfs = new HashMap<>();
285    if (tableCfs != null) {
286      tableCfs.forEach(
287        (table, cfs) -> newTableCfs.put(table, cfs != null ? Lists.newArrayList(cfs) : null));
288    }
289    return newTableCfs;
290  }
291
292  /**
293   * Set the replicable table-cf config of the specified peer
294   * @param id a short name that identifies the cluster
295   * @param tableCfs the table and column-family list which will be replicated for this peer.
296   * A map from tableName to column family names. An empty collection can be passed
297   * to indicate replicating all column families. Pass null for replicating all table and column
298   * families
299   */
300  @Deprecated
301  public void setPeerTableCFs(String id, Map<TableName, ? extends Collection<String>> tableCfs)
302      throws IOException {
303    ReplicationPeerConfig peerConfig = getPeerConfig(id);
304    peerConfig.setTableCFsMap(tableCfs);
305    updatePeerConfig(id, peerConfig);
306  }
307
308  /**
309   * Get the state of the specified peer cluster
310   * @param id String format of the Short name that identifies the peer,
311   * an IllegalArgumentException is thrown if it doesn't exist
312   * @return true if replication is enabled to that peer, false if it isn't
313   */
314  @Deprecated
315  public boolean getPeerState(String id) throws ReplicationException, IOException {
316    List<ReplicationPeerDescription> peers = admin.listReplicationPeers(Pattern.compile(id));
317    if (peers.isEmpty() || !id.equals(peers.get(0).getPeerId())) {
318      throw new ReplicationPeerNotFoundException(id);
319    }
320    return peers.get(0).isEnabled();
321  }
322
323  @Override
324  public void close() throws IOException {
325    if (this.connection != null) {
326      this.connection.close();
327    }
328    admin.close();
329  }
330
331  /**
332   * Find all column families that are replicated from this cluster
333   * @return the full list of the replicated column families of this cluster as:
334   *        tableName, family name, replicationType
335   *
336   * Currently replicationType is Global. In the future, more replication
337   * types may be extended here. For example
338   *  1) the replication may only apply to selected peers instead of all peers
339   *  2) the replicationType may indicate the host Cluster servers as Slave
340   *     for the table:columnFam.
341   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#listReplicatedTableCFs()} instead
342   */
343  @Deprecated
344  public List<HashMap<String, String>> listReplicated() throws IOException {
345    List<HashMap<String, String>> replicationColFams = new ArrayList<>();
346    admin.listReplicatedTableCFs().forEach(
347      (tableCFs) -> {
348        String table = tableCFs.getTable().getNameAsString();
349        tableCFs.getColumnFamilyMap()
350            .forEach(
351              (cf, scope) -> {
352                HashMap<String, String> replicationEntry = new HashMap<>();
353                replicationEntry.put(TNAME, table);
354                replicationEntry.put(CFNAME, cf);
355                replicationEntry.put(REPLICATIONTYPE, REPLICATIONGLOBAL);
356                replicationColFams.add(replicationEntry);
357              });
358      });
359    return replicationColFams;
360  }
361
362  /**
363   * Enable a table's replication switch.
364   * @param tableName name of the table
365   * @throws IOException if a remote or network exception occurs
366   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#enableTableReplication(TableName)}
367   *             instead
368   */
369  @Deprecated
370  public void enableTableRep(final TableName tableName) throws IOException {
371    admin.enableTableReplication(tableName);
372  }
373
374  /**
375   * Disable a table's replication switch.
376   * @param tableName name of the table
377   * @throws IOException if a remote or network exception occurs
378   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#disableTableReplication(TableName)}
379   *             instead
380   */
381  @Deprecated
382  public void disableTableRep(final TableName tableName) throws IOException {
383    admin.disableTableReplication(tableName);
384  }
385
386  /**
387   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#listReplicationPeers()} instead
388   */
389  @InterfaceAudience.Private
390  @Deprecated
391  List<ReplicationPeerDescription> listReplicationPeers() throws IOException {
392    return admin.listReplicationPeers();
393  }
394}