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