/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * 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.linkedin.pinot.tools.admin.command; import com.linkedin.pinot.common.utils.NetUtil; import com.linkedin.pinot.controller.ControllerConf; import com.linkedin.pinot.controller.ControllerStarter; import com.linkedin.pinot.tools.Command; import java.io.File; import org.apache.commons.configuration.ConfigurationException; import org.kohsuke.args4j.Option; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Class to implement StartController command. * */ public class StartControllerCommand extends AbstractBaseAdminCommand implements Command { private static final Logger LOGGER = LoggerFactory.getLogger(StartControllerCommand.class); @Option(name = "-controllerHost", required = false, metaVar = "<String>", usage = "host name for controller.") private String _controllerHost; @Option(name = "-controllerPort", required = false, metaVar = "<int>", usage = "Port number to start the controller at.") private String _controllerPort = DEFAULT_CONTROLLER_PORT; @Option(name = "-dataDir", required = false, metaVar = "<string>", usage = "Path to directory containging data.") private String _dataDir = TMP_DIR + "PinotController"; @Option(name = "-zkAddress", required = false, metaVar = "<http>", usage = "Http address of Zookeeper.") private String _zkAddress = DEFAULT_ZK_ADDRESS; @Option(name = "-clusterName", required = false, metaVar = "<String>", usage = "Pinot cluster name.") private String _clusterName = DEFAULT_CLUSTER_NAME; @Option(name = "-configFileName", required = false, metaVar = "<FilePathName>", usage = "Controller Starter config file", forbids = { "-controllerHost", "-controllerPort", "-dataDir", "-zkAddress", "-clusterName" }) private String _configFileName; @Option(name = "-help", required = false, help = true, aliases = { "-h", "--h", "--help" }, usage = "Print this message.") private boolean _help = false; // This can be set via the set method, or via config file input. private boolean _tenantIsolation = true; @Override public boolean getHelp() { return _help; } public StartControllerCommand setControllerPort(String controllerPort) { _controllerPort = controllerPort; return this; } public StartControllerCommand setDataDir(String dataDir) { _dataDir = dataDir; return this; } public StartControllerCommand setZkAddress(String zkAddress) { _zkAddress = zkAddress; return this; } public StartControllerCommand setTenantIsolation(boolean tenantIsolation) { _tenantIsolation = tenantIsolation; return this; } public StartControllerCommand setConfigFileName(String configFileName) { _configFileName = configFileName; return this; } public StartControllerCommand setClusterName(String clusterName) { _clusterName = clusterName; return this; } @Override public String getName() { return "StartController"; } @Override public String toString() { if (_configFileName != null) { return ("StartController -configFileName " + _configFileName); } else { return ("StartController -clusterName " + _clusterName + " -controllerHost " + _controllerHost + " -controllerPort " + _controllerPort + " -dataDir " + _dataDir + " -zkAddress " + _zkAddress); } } @Override public void cleanup() { } @Override public String description() { return "Start the Pinot Controller Process at the specified port."; } @Override public boolean execute() throws Exception { if (_controllerHost == null) { _controllerHost = NetUtil.getHostAddress(); } ControllerConf conf = readConfigFromFile(_configFileName); if (conf == null) { if (_configFileName != null) { LOGGER.error("Error: Unable to find file {}.", _configFileName); return false; } conf = new ControllerConf(); conf.setControllerHost(_controllerHost); conf.setControllerPort(_controllerPort); conf.setDataDir(_dataDir); conf.setZkStr(_zkAddress); conf.setHelixClusterName(_clusterName); conf.setControllerVipHost(_controllerHost); conf.setTenantIsolationEnabled(_tenantIsolation); conf.setRetentionControllerFrequencyInSeconds(3600 * 6); conf.setValidationControllerFrequencyInSeconds(3600); } LOGGER.info("Executing command: " + toString()); final ControllerStarter starter = new ControllerStarter(conf); starter.start(); String pidFile = ".pinotAdminController-" + String.valueOf(System.currentTimeMillis()) + ".pid"; savePID(System.getProperty("java.io.tmpdir") + File.separator + pidFile); return true; } @Override ControllerConf readConfigFromFile(String configFileName) throws ConfigurationException { ControllerConf conf = null; if (configFileName == null) { return null; } File configFile = new File(_configFileName); if (!configFile.exists()) { return null; } conf = new ControllerConf(configFile); return (validateConfig(conf)) ? conf : null; } private boolean validateConfig(ControllerConf conf) { if (conf == null) { LOGGER.error("Error: Null conf object."); return false; } if (conf.getControllerHost() == null) { LOGGER.error("Error: missing hostname, please specify 'controller.host' property in config file."); return false; } if (conf.getControllerPort() == null) { LOGGER.error("Error: missing controller port, please specify 'controller.port' property in config file."); return false; } if (conf.getZkStr() == null) { LOGGER.error("Error: missing Zookeeper address, please specify 'controller.zk.str' property in config file."); return false; } if (conf.getHelixClusterName() == null) { LOGGER.error( "Error: missing helix cluster name, please specify 'controller.helix.cluster.name' property in config file."); return false; } return true; } }