/** * 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 static org.apache.commons.lang3.StringUtils.isBlank; import java.io.FileInputStream; import java.net.URI; import java.net.URL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.yahoo.pulsar.broker.PulsarService; import com.yahoo.pulsar.broker.ServiceConfiguration; import com.yahoo.pulsar.broker.ServiceConfigurationUtils; import com.yahoo.pulsar.client.admin.PulsarAdmin; import com.yahoo.pulsar.client.admin.PulsarAdminException; import com.yahoo.pulsar.common.configuration.PulsarConfigurationLoader; import com.yahoo.pulsar.common.policies.data.ClusterData; import com.yahoo.pulsar.common.policies.data.PropertyAdmin; import com.yahoo.pulsar.zookeeper.LocalBookkeeperEnsemble; public class PulsarStandaloneStarter { PulsarService broker; PulsarAdmin admin; LocalBookkeeperEnsemble bkEnsemble; ServiceConfiguration config; @Parameter(names = { "-c", "--config" }, description = "Configuration file path", required = true) private String configFile; @Parameter(names = { "--wipe-data" }, description = "Clean up previous ZK/BK data") private boolean wipeData = false; @Parameter(names = { "--num-bookies" }, description = "Number of local Bookies") private int numOfBk = 1; @Parameter(names = { "--zookeeper-port" }, description = "Local zookeeper's port") private int zkPort = 2181; @Parameter(names = { "--bookkeeper-port" }, description = "Local bookies base port") private int bkPort = 3181; @Parameter(names = { "--zookeeper-dir" }, description = "Local zooKeeper's data directory") private String zkDir = "data/standalone/zookeeper"; @Parameter(names = { "--bookkeeper-dir" }, description = "Local bookies base data directory") private String bkDir = "data/standalone/bookkeeper"; @Parameter(names = { "--no-broker" }, description = "Only start ZK and BK services, no broker") private boolean noBroker = false; @Parameter(names = { "--only-broker" }, description = "Only start Pulsar broker service (no ZK, BK)") private boolean onlyBroker = false; @Parameter(names = { "-a", "--advertised-address" }, description = "Standalone broker advertised address") private String advertisedAddress = null; @Parameter(names = { "-h", "--help" }, description = "Show this help message") private boolean help = false; private static final Logger log = LoggerFactory.getLogger(PulsarStandaloneStarter.class); public PulsarStandaloneStarter(String[] args) throws Exception { JCommander jcommander = new JCommander(); try { jcommander.addObject(this); jcommander.parse(args); if (help || isBlank(configFile)) { jcommander.usage(); return; } if (noBroker && onlyBroker) { log.error("Only one option is allowed between '--no-broker' and '--only-broker'"); jcommander.usage(); return; } } catch (Exception e) { jcommander.usage(); return; } this.config = PulsarConfigurationLoader.create((new FileInputStream(configFile)), ServiceConfiguration.class); PulsarConfigurationLoader.isComplete(config); // Set ZK server's host to localhost config.setZookeeperServers("127.0.0.1:" + zkPort); config.setGlobalZookeeperServers("127.0.0.1:" + zkPort); config.setWebSocketServiceEnabled(true); if (advertisedAddress != null) { // Use advertised address from command line config.setAdvertisedAddress(advertisedAddress); } else if (isBlank(config.getAdvertisedAddress())) { // Use advertised address as local hostname config.setAdvertisedAddress(ServiceConfigurationUtils.unsafeLocalhostResolve()); } else { // Use advertised address from config file } Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { if (broker != null) { broker.close(); } if (bkEnsemble != null) { bkEnsemble.stop(); } } catch (Exception e) { log.error("Shutdown failed: {}", e.getMessage()); } } }); } void start() throws Exception { if (config == null) { System.exit(1); } log.debug("--- setup PulsarStandaloneStarter ---"); if (!onlyBroker) { // Start LocalBookKeeper bkEnsemble = new LocalBookkeeperEnsemble(numOfBk, zkPort, bkPort, zkDir, bkDir, wipeData); bkEnsemble.start(); } if (noBroker) { return; } // Start Broker broker = new PulsarService(config); broker.start(); // Create a sample namespace URL webServiceUrl = new URL( String.format("http://%s:%d", config.getAdvertisedAddress(), config.getWebServicePort())); String brokerServiceUrl = String.format("pulsar://%s:%d", config.getAdvertisedAddress(), config.getBrokerServicePort()); admin = new PulsarAdmin(webServiceUrl, config.getBrokerClientAuthenticationPlugin(), config.getBrokerClientAuthenticationParameters()); String property = "sample"; String cluster = config.getClusterName(); String namespace = property + "/" + cluster + "/ns1"; try { ClusterData clusterData = new ClusterData(webServiceUrl.toString(), null /* serviceUrlTls */, brokerServiceUrl, null /* brokerServiceUrlTls */); if (!admin.clusters().getClusters().contains(cluster)) { admin.clusters().createCluster(cluster, clusterData); } else { admin.clusters().updateCluster(cluster, clusterData); } if (!admin.properties().getProperties().contains(property)) { admin.properties().createProperty(property, new PropertyAdmin(Lists.newArrayList(config.getSuperUserRoles()), Sets.newHashSet(cluster))); } if (!admin.namespaces().getNamespaces(property).contains(namespace)) { admin.namespaces().createNamespace(namespace); } } catch (PulsarAdminException e) { log.info(e.getMessage()); } log.debug("--- setup completed ---"); } public static void main(String args[]) throws Exception { // Start standalone PulsarStandaloneStarter standalone = new PulsarStandaloneStarter(args); standalone.start(); } }