blob: c40c5f2522fdafb6e000af832e169473dc99845d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.slider.providers.hbase;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.yarn.api.records.LocalResource;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.common.SliderXmlConfKeys;
import org.apache.slider.api.OptionKeys;
import org.apache.slider.core.conf.AggregateConf;
import org.apache.slider.core.conf.ConfTreeOperations;
import org.apache.slider.core.conf.MapOperations;
import org.apache.slider.core.launch.AbstractLauncher;
import org.apache.slider.core.exceptions.BadCommandArgumentsException;
import org.apache.slider.core.exceptions.BadConfigException;
import org.apache.slider.core.exceptions.SliderException;
import org.apache.slider.providers.AbstractClientProvider;
import org.apache.slider.providers.ProviderRole;
import org.apache.slider.providers.ProviderUtils;
import org.apache.slider.common.tools.ConfigHelper;
import org.apache.slider.common.tools.SliderFileSystem;
import org.apache.slider.common.tools.SliderUtils;
import org.apache.slider.core.zk.ZookeeperUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This class implements the client-side aspects
* of an HBase Cluster
*/
public class HBaseClientProvider extends AbstractClientProvider implements
HBaseKeys, SliderKeys,
HBaseConfigFileOptions {
protected static final Logger log =
LoggerFactory.getLogger(HBaseClientProvider.class);
protected static final String NAME = "hbase";
private static final String INSTANCE_RESOURCE_BASE = "/org/apache/slider/providers/hbase/instance/";
protected HBaseClientProvider(Configuration conf) {
super(conf);
}
@Override
public String getName() {
return NAME;
}
@Override
public List<ProviderRole> getRoles() {
return HBaseRoles.getRoles();
}
@Override
public void prepareInstanceConfiguration(AggregateConf aggregateConf) throws
SliderException,
IOException {
String resourceTemplate = INSTANCE_RESOURCE_BASE + "resources.json";
String appConfTemplate = INSTANCE_RESOURCE_BASE + "appconf.json";
mergeTemplates(aggregateConf, null, resourceTemplate, appConfTemplate);
}
/**
* Build the hdfs-site.xml file
* This the configuration used by HBase directly
* @param instanceDescription this is the cluster specification used to define this
* @return a map of the dynamic bindings for this Slider instance
*/
public Map<String, String> buildSiteConfFromInstance(
AggregateConf instanceDescription)
throws BadConfigException {
ConfTreeOperations appconf =
instanceDescription.getAppConfOperations();
MapOperations globalAppOptions = appconf.getGlobalOptions();
MapOperations globalInstanceOptions = instanceDescription.getInternalOperations().getGlobalOptions();
MapOperations master = appconf.getMandatoryComponent(HBaseKeys.ROLE_MASTER);
MapOperations worker = appconf.getMandatoryComponent(HBaseKeys.ROLE_WORKER);
Map<String, String> sitexml = new HashMap<>();
//map all cluster-wide site. options
providerUtils.propagateSiteOptions(globalAppOptions, sitexml);
/*
//this is where we'd do app-indepdenent keytabs
String keytab =
clusterSpec.getOption(OptionKeys.OPTION_KEYTAB_LOCATION, "");
*/
sitexml.put(KEY_HBASE_ROOTDIR,
globalInstanceOptions.getMandatoryOption(
OptionKeys.INTERNAL_DATA_DIR_PATH)
);
providerUtils.propagateOption(globalAppOptions, OptionKeys.ZOOKEEPER_PATH,
sitexml, KEY_ZNODE_PARENT);
String quorum =
globalAppOptions.getMandatoryOption(OptionKeys.ZOOKEEPER_QUORUM);
sitexml.put(KEY_ZOOKEEPER_QUORUM, ZookeeperUtils.convertToHostsOnlyList(quorum));
//and assume first port works everywhere
sitexml.put(KEY_ZOOKEEPER_PORT,
Integer.toString(ZookeeperUtils.getFirstPort(quorum, HBASE_ZK_PORT)));
return sitexml;
}
@Override //Client
public void preflightValidateClusterConfiguration(SliderFileSystem sliderFileSystem,
String clustername,
Configuration configuration,
AggregateConf instanceDefinition,
Path clusterDirPath,
Path generatedConfDirPath,
boolean secure) throws
SliderException,
IOException {
super.preflightValidateClusterConfiguration(sliderFileSystem, clustername,
configuration,
instanceDefinition,
clusterDirPath,
generatedConfDirPath, secure);
Path templatePath = new Path(generatedConfDirPath, HBaseKeys.SITE_XML);
//load the HBase site file or fail
Configuration siteConf = ConfigHelper.loadConfiguration(sliderFileSystem.getFileSystem(),
templatePath);
//core customizations
validateHBaseSiteXML(siteConf, secure, templatePath.toString());
}
/**
* Validate the hbase-site.xml values
* @param siteConf site config
* @param secure secure flag
* @param origin origin for exceptions
* @throws BadConfigException if a config is missing/invalid
*/
public void validateHBaseSiteXML(Configuration siteConf,
boolean secure,
String origin) throws BadConfigException {
try {
SliderUtils.verifyOptionSet(siteConf, KEY_HBASE_CLUSTER_DISTRIBUTED,
false);
SliderUtils.verifyOptionSet(siteConf, KEY_HBASE_ROOTDIR, false);
SliderUtils.verifyOptionSet(siteConf, KEY_ZNODE_PARENT, false);
SliderUtils.verifyOptionSet(siteConf, KEY_ZOOKEEPER_QUORUM, false);
SliderUtils.verifyOptionSet(siteConf, KEY_ZOOKEEPER_PORT, false);
int zkPort =
siteConf.getInt(HBaseConfigFileOptions.KEY_ZOOKEEPER_PORT, 0);
if (zkPort == 0) {
throw new BadConfigException(
"ZK port property not provided at %s in configuration file %s",
HBaseConfigFileOptions.KEY_ZOOKEEPER_PORT,
siteConf);
}
if (secure) {
//better have the secure cluster definition up and running
SliderUtils.verifyOptionSet(siteConf, KEY_MASTER_KERBEROS_PRINCIPAL,
false);
SliderUtils.verifyOptionSet(siteConf, KEY_MASTER_KERBEROS_KEYTAB,
false);
SliderUtils.verifyOptionSet(siteConf,
KEY_REGIONSERVER_KERBEROS_PRINCIPAL,
false);
SliderUtils.verifyOptionSet(siteConf,
KEY_REGIONSERVER_KERBEROS_KEYTAB, false);
}
} catch (BadConfigException e) {
//bad configuration, dump it
log.error("Bad site configuration {} : {}", origin, e, e);
log.info(ConfigHelper.dumpConfigToString(siteConf));
throw e;
}
}
private static Set<String> knownRoleNames = new HashSet<>();
static {
List<ProviderRole> roles = HBaseRoles.getRoles();
knownRoleNames.add(SliderKeys.COMPONENT_AM);
for (ProviderRole role : roles) {
knownRoleNames.add(role.name);
}
}
/**
* Validate the instance definition.
* @param instanceDefinition instance definition
*/
@Override
public void validateInstanceDefinition(AggregateConf instanceDefinition) throws
SliderException {
super.validateInstanceDefinition(instanceDefinition);
ConfTreeOperations resources =
instanceDefinition.getResourceOperations();
Set<String> unknownRoles = resources.getComponentNames();
unknownRoles.removeAll(knownRoleNames);
if (!unknownRoles.isEmpty()) {
throw new BadCommandArgumentsException("Unknown component: %s",
unknownRoles.iterator().next());
}
providerUtils.validateNodeCount(instanceDefinition, HBaseKeys.ROLE_WORKER,
0, -1);
providerUtils.validateNodeCount(instanceDefinition, HBaseKeys.ROLE_MASTER,
0, -1);
}
@Override
public void prepareAMAndConfigForLaunch(SliderFileSystem fileSystem,
Configuration serviceConf,
AbstractLauncher launcher,
AggregateConf instanceDescription,
Path snapshotConfDirPath,
Path generatedConfDirPath,
Configuration clientConfExtras,
String libdir,
Path tempPath, boolean miniClusterTestRun) throws
IOException,
SliderException {
// add any and all dependency files
Map<String, LocalResource> providerResources =
new HashMap<>();
ProviderUtils.addProviderJar(providerResources,
this,
"slider-hbase-provider.jar",
fileSystem,
tempPath,
libdir, miniClusterTestRun);
Class<?>[] classes = {
};
String[] jars =
{
};
ProviderUtils.addDependencyJars(providerResources, fileSystem, tempPath,
libdir, jars,
classes);
launcher.addLocalResources(providerResources);
//load in the template site config
log.debug("Loading template configuration from {}", snapshotConfDirPath);
Configuration siteConf = ConfigHelper.loadTemplateConfiguration(
serviceConf,
snapshotConfDirPath,
HBaseKeys.SITE_XML,
HBaseKeys.HBASE_TEMPLATE_RESOURCE);
if (log.isDebugEnabled()) {
log.debug("Configuration came from {}",
siteConf.get(SliderXmlConfKeys.KEY_TEMPLATE_ORIGIN));
ConfigHelper.dumpConf(siteConf);
}
//construct the cluster configuration values
ConfTreeOperations appconf =
instanceDescription.getAppConfOperations();
Map<String, String> clusterConfMap = buildSiteConfFromInstance(
instanceDescription);
//merge them
ConfigHelper.addConfigMap(siteConf,
clusterConfMap.entrySet(),
"HBase Provider");
//now, if there is an extra client conf, merge it in too
if (clientConfExtras != null) {
ConfigHelper.mergeConfigurations(siteConf, clientConfExtras,
"Slider Client");
}
if (log.isDebugEnabled()) {
log.debug("Merged Configuration");
ConfigHelper.dumpConf(siteConf);
}
Path sitePath = ConfigHelper.saveConfig(serviceConf,
siteConf,
generatedConfDirPath,
HBaseKeys.SITE_XML);
log.debug("Saving the config to {}", sitePath);
launcher.submitDirectory(generatedConfDirPath,
SliderKeys.PROPAGATED_CONF_DIR_NAME);
}
}