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
179   * @deprecated
180   */
181  @Deprecated
182  public int getPeersCount() throws IOException {
183    return this.admin.listReplicationPeers().size();
184  }
185
186  /**
187   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#listReplicationPeers()} instead
188   */
189  @Deprecated
190  public Map<String, ReplicationPeerConfig> listPeerConfigs() throws IOException {
191    List<ReplicationPeerDescription> peers = this.admin.listReplicationPeers();
192    Map<String, ReplicationPeerConfig> result = new TreeMap<>();
193    for (ReplicationPeerDescription peer : peers) {
194      result.put(peer.getPeerId(), peer.getPeerConfig());
195    }
196    return result;
197  }
198
199  /**
200   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#getReplicationPeerConfig(String)}
201   *             instead
202   */
203  @Deprecated
204  public ReplicationPeerConfig getPeerConfig(String id) throws IOException {
205    return admin.getReplicationPeerConfig(id);
206  }
207
208  /**
209   * Get the replicable table-cf config of the specified peer.
210   * @param id a short name that identifies the cluster
211   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0, use
212   *             {@link #getPeerConfig(String)} instead.
213   */
214  @Deprecated
215  public String getPeerTableCFs(String id) throws IOException {
216    ReplicationPeerConfig peerConfig = admin.getReplicationPeerConfig(id);
217    return ReplicationPeerConfigUtil.convertToString(peerConfig.getTableCFsMap());
218  }
219
220  /**
221   * Append the replicable table-cf config of the specified peer
222   * @param id       a short that identifies the cluster
223   * @param tableCfs table-cfs config str
224   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0, use
225   *             {@link #appendPeerTableCFs(String, Map)} instead.
226   */
227  @Deprecated
228  public void appendPeerTableCFs(String id, String tableCfs)
229    throws ReplicationException, IOException {
230    appendPeerTableCFs(id, ReplicationPeerConfigUtil.parseTableCFsFromConfig(tableCfs));
231  }
232
233  /**
234   * Append the replicable table-cf config of the specified peer
235   * @param id       a short that identifies the cluster
236   * @param tableCfs A map from tableName to column family names
237   */
238  @Deprecated
239  public void appendPeerTableCFs(String id, Map<TableName, ? extends Collection<String>> tableCfs)
240    throws ReplicationException, IOException {
241    this.admin.appendReplicationPeerTableCFs(id, copyTableCFs(tableCfs));
242  }
243
244  /**
245   * Remove some table-cfs from table-cfs config of the specified peer
246   * @param id      a short name that identifies the cluster
247   * @param tableCf table-cfs config str
248   * @deprecated as release of 2.0.0, and it will be removed in 3.0.0, use
249   *             {@link #removePeerTableCFs(String, Map)} instead.
250   */
251  @Deprecated
252  public void removePeerTableCFs(String id, String tableCf)
253    throws ReplicationException, IOException {
254    removePeerTableCFs(id, ReplicationPeerConfigUtil.parseTableCFsFromConfig(tableCf));
255  }
256
257  /**
258   * Remove some table-cfs from config of the specified peer
259   * @param id       a short name that identifies the cluster
260   * @param tableCfs A map from tableName to column family names
261   */
262  @Deprecated
263  public void removePeerTableCFs(String id, Map<TableName, ? extends Collection<String>> tableCfs)
264    throws ReplicationException, IOException {
265    this.admin.removeReplicationPeerTableCFs(id, copyTableCFs(tableCfs));
266  }
267
268  private Map<TableName, List<String>>
269    copyTableCFs(Map<TableName, ? extends Collection<String>> tableCfs) {
270    Map<TableName, List<String>> newTableCfs = new HashMap<>();
271    if (tableCfs != null) {
272      tableCfs.forEach(
273        (table, cfs) -> newTableCfs.put(table, cfs != null ? Lists.newArrayList(cfs) : null));
274    }
275    return newTableCfs;
276  }
277
278  /**
279   * Set the replicable table-cf config of the specified peer
280   * @param id       a short name that identifies the cluster
281   * @param tableCfs the table and column-family list which will be replicated for this peer. A map
282   *                 from tableName to column family names. An empty collection can be passed to
283   *                 indicate replicating all column families. Pass null for replicating all table
284   *                 and column families
285   */
286  @Deprecated
287  public void setPeerTableCFs(String id, Map<TableName, ? extends Collection<String>> tableCfs)
288    throws IOException {
289    ReplicationPeerConfig peerConfig = getPeerConfig(id);
290    peerConfig.setTableCFsMap(tableCfs);
291    updatePeerConfig(id, peerConfig);
292  }
293
294  /**
295   * Get the state of the specified peer cluster
296   * @param id String format of the Short name that identifies the peer, an IllegalArgumentException
297   *           is thrown if it doesn't exist
298   * @return true if replication is enabled to that peer, false if it isn't
299   */
300  @Deprecated
301  public boolean getPeerState(String id) throws ReplicationException, IOException {
302    List<ReplicationPeerDescription> peers = admin.listReplicationPeers(Pattern.compile(id));
303    if (peers.isEmpty() || !id.equals(peers.get(0).getPeerId())) {
304      throw new ReplicationPeerNotFoundException(id);
305    }
306    return peers.get(0).isEnabled();
307  }
308
309  @Override
310  public void close() throws IOException {
311    if (this.connection != null) {
312      this.connection.close();
313    }
314    admin.close();
315  }
316
317  /**
318   * Find all column families that are replicated from this cluster
319   * @return the full list of the replicated column families of this cluster as: tableName, family
320   *         name, replicationType Currently replicationType is Global. In the future, more
321   *         replication types may be extended here. For example 1) the replication may only apply
322   *         to selected peers instead of all peers 2) the replicationType may indicate the host
323   *         Cluster servers as Slave for the table:columnFam.
324   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#listReplicatedTableCFs()} instead
325   */
326  @Deprecated
327  public List<HashMap<String, String>> listReplicated() throws IOException {
328    List<HashMap<String, String>> replicationColFams = new ArrayList<>();
329    admin.listReplicatedTableCFs().forEach((tableCFs) -> {
330      String table = tableCFs.getTable().getNameAsString();
331      tableCFs.getColumnFamilyMap().forEach((cf, scope) -> {
332        HashMap<String, String> replicationEntry = new HashMap<>();
333        replicationEntry.put(TNAME, table);
334        replicationEntry.put(CFNAME, cf);
335        replicationEntry.put(REPLICATIONTYPE, REPLICATIONGLOBAL);
336        replicationColFams.add(replicationEntry);
337      });
338    });
339    return replicationColFams;
340  }
341
342  /**
343   * Enable a table's replication switch.
344   * @param tableName name of the table
345   * @throws IOException if a remote or network exception occurs
346   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#enableTableReplication(TableName)}
347   *             instead
348   */
349  @Deprecated
350  public void enableTableRep(final TableName tableName) throws IOException {
351    admin.enableTableReplication(tableName);
352  }
353
354  /**
355   * Disable a table's replication switch.
356   * @param tableName name of the table
357   * @throws IOException if a remote or network exception occurs
358   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#disableTableReplication(TableName)}
359   *             instead
360   */
361  @Deprecated
362  public void disableTableRep(final TableName tableName) throws IOException {
363    admin.disableTableReplication(tableName);
364  }
365
366  /**
367   * @deprecated use {@link org.apache.hadoop.hbase.client.Admin#listReplicationPeers()} instead
368   */
369  @InterfaceAudience.Private
370  @Deprecated
371  List<ReplicationPeerDescription> listReplicationPeers() throws IOException {
372    return admin.listReplicationPeers();
373  }
374}