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