/** * Copyright 2016 Yahoo Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.yahoo.pulsar; import java.io.IOException; import org.apache.bookkeeper.client.BookKeeperAdmin; import org.apache.bookkeeper.conf.ClientConfiguration; import org.apache.bookkeeper.meta.HierarchicalLedgerManagerFactory; import org.apache.bookkeeper.util.ZkUtils; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException.NodeExistsException; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.yahoo.pulsar.common.policies.data.ClusterData; import com.yahoo.pulsar.common.util.ObjectMapperFactory; import com.yahoo.pulsar.zookeeper.ZooKeeperClientFactory; import com.yahoo.pulsar.zookeeper.ZooKeeperClientFactory.SessionType; import com.yahoo.pulsar.zookeeper.ZookeeperClientFactoryImpl; /** * Setup the metadata for a new Pulsar cluster */ public class PulsarClusterMetadataSetup { private static class Arguments { @Parameter(names = { "-c", "--cluster" }, description = "Cluster name", required = true) private String cluster; @Parameter(names = { "-uw", "--web-service-url" }, description = "Web-service URL for new cluster", required = true) private String clusterWebServiceUrl; @Parameter(names = { "-tw", "--web-service-url-tls" }, description = "Web-service URL for new cluster with TLS encryption", required = false) private String clusterWebServiceUrlTls; @Parameter(names = { "-ub", "--broker-service-url" }, description = "Broker-service URL for new cluster", required = false) private String clusterBrokerServiceUrl; @Parameter(names = { "-tb", "--broker-service-url-tls" }, description = "Broker-service URL for new cluster with TLS encryption", required = false) private String clusterBrokerServiceUrlTls; @Parameter(names = { "-zk", "--zookeeper" }, description = "Local ZooKeeper quorum connection string", required = true) private String zookeeper; @Parameter(names = { "-gzk", "--global-zookeeper" }, description = "Global ZooKeeper quorum connection string", required = true) private String globalZookeeper; @Parameter(names = { "-h", "--help" }, description = "Show this help message") private boolean help = false; } public static void main(String[] args) throws Exception { Arguments arguments = new Arguments(); JCommander jcommander = new JCommander(); try { jcommander.addObject(arguments); jcommander.parse(args); if (arguments.help) { jcommander.usage(); return; } } catch (Exception e) { jcommander.usage(); return; } log.info("Setting up cluster {} with zk={} global-zk={}", arguments.cluster, arguments.zookeeper, arguments.globalZookeeper); // Format BookKeeper metadata ClientConfiguration bkConf = new ClientConfiguration(); bkConf.setLedgerManagerFactoryClass(HierarchicalLedgerManagerFactory.class); bkConf.setZkServers(arguments.zookeeper); if (!BookKeeperAdmin.format(bkConf, false /* interactive */, false /* force */)) { throw new IOException("Failed to initialize BookKeeper metadata"); } ZooKeeperClientFactory zkfactory = new ZookeeperClientFactoryImpl(); ZooKeeper localZk = zkfactory.create(arguments.zookeeper, SessionType.ReadWrite, 30000).get(); ZooKeeper globalZk = zkfactory.create(arguments.globalZookeeper, SessionType.ReadWrite, 30000).get(); localZk.create("/managed-ledgers", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); localZk.create("/namespace", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); try { ZkUtils.createFullPathOptimistic(globalZk, "/admin/policies", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } catch (NodeExistsException e) { // Ignore } try { ZkUtils.createFullPathOptimistic(globalZk, "/admin/clusters", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } catch (NodeExistsException e) { // Ignore } ClusterData clusterData = new ClusterData(arguments.clusterWebServiceUrl, arguments.clusterWebServiceUrlTls, arguments.clusterBrokerServiceUrl, arguments.clusterBrokerServiceUrlTls); byte[] clusterDataJson = ObjectMapperFactory.getThreadLocal().writeValueAsBytes(clusterData); globalZk.create("/admin/clusters/" + arguments.cluster, clusterDataJson, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); // Create marker for "global" cluster ClusterData globalClusterData = new ClusterData(null, null); byte[] globalClusterDataJson = ObjectMapperFactory.getThreadLocal().writeValueAsBytes(globalClusterData); try { globalZk.create("/admin/clusters/global", globalClusterDataJson, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } catch (NodeExistsException e) { // Ignore } log.info("Cluster metadata for '{}' setup correctly", arguments.cluster); } private static final Logger log = LoggerFactory.getLogger(PulsarClusterMetadataSetup.class); }