blob: fc2397093282fcc83ae8723630e05590ff09ed01 [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.Container;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.api.ClusterDescription;
import org.apache.slider.api.OptionKeys;
import org.apache.slider.api.RoleKeys;
import org.apache.slider.api.StatusKeys;
import org.apache.slider.core.conf.AggregateConf;
import org.apache.slider.core.conf.MapOperations;
import org.apache.slider.core.launch.CommandLineBuilder;
import org.apache.slider.core.launch.ContainerLauncher;
import org.apache.slider.core.exceptions.BadCommandArgumentsException;
import org.apache.slider.core.exceptions.SliderException;
import org.apache.slider.core.exceptions.SliderInternalStateException;
import org.apache.slider.core.registry.docstore.PublishedConfigSet;
import org.apache.slider.core.registry.docstore.PublishedConfiguration;
import org.apache.slider.core.registry.info.ServiceInstanceData;
import org.apache.slider.providers.AbstractProviderService;
import org.apache.slider.providers.ProviderCore;
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.server.appmaster.web.rest.agent.AgentRestOperations;
import org.apache.slider.server.appmaster.web.rest.agent.HeartBeat;
import org.apache.slider.server.appmaster.web.rest.agent.HeartBeatResponse;
import org.apache.slider.server.appmaster.web.rest.agent.Register;
import org.apache.slider.server.appmaster.web.rest.agent.RegistrationResponse;
import org.apache.slider.server.appmaster.web.rest.agent.RegistrationStatus;
import org.apache.slider.server.services.utility.EventCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.slider.server.appmaster.web.rest.RestPaths.SLIDER_PATH_PUBLISHER;
/**
* This class implements the server-side aspects
* of an HBase Cluster
*/
public class HBaseProviderService extends AbstractProviderService implements
ProviderCore,
HBaseKeys,
SliderKeys,
AgentRestOperations{
protected static final Logger log =
LoggerFactory.getLogger(HBaseProviderService.class);
private static final ProviderUtils providerUtils = new ProviderUtils(log);
private HBaseClientProvider clientProvider;
private Configuration siteConf;
public HBaseProviderService() {
super("HBaseProviderService");
setAgentRestOperations(this);
}
@Override
public List<ProviderRole> getRoles() {
return HBaseRoles.getRoles();
}
@Override
protected void serviceInit(Configuration conf) throws Exception {
super.serviceInit(conf);
clientProvider = new HBaseClientProvider(conf);
}
@Override
public Configuration loadProviderConfigurationInformation(File confDir)
throws BadCommandArgumentsException, IOException {
return loadProviderConfigurationInformation(confDir, SITE_XML);
}
/**
* Validate the cluster specification. This can be invoked on both
* server and client
* @param instanceDefinition the instance definition to validate
*/
@Override // Client and Server
public void validateInstanceDefinition(AggregateConf instanceDefinition) throws
SliderException {
clientProvider.validateInstanceDefinition(instanceDefinition);
}
@Override
public void buildContainerLaunchContext(ContainerLauncher launcher,
AggregateConf instanceDefinition,
Container container,
String role,
SliderFileSystem coreFS,
Path generatedConfPath,
MapOperations resourceComponent,
MapOperations appComponent,
Path containerTmpDirPath) throws IOException, SliderException {
// Set the environment
launcher.putEnv(SliderUtils.buildEnvMap(appComponent));
launcher.setEnv(HBASE_LOG_DIR, providerUtils.getLogdir());
launcher.setEnv(PROPAGATED_CONFDIR,
ProviderUtils.convertToAppRelativePath(
SliderKeys.PROPAGATED_CONF_DIR_NAME) );
//local resources
//add the configuration resources
launcher.addLocalResources(coreFS.submitDirectory(
generatedConfPath,
SliderKeys.PROPAGATED_CONF_DIR_NAME));
//Add binaries
//now add the image if it was set
String imageURI = instanceDefinition.getInternalOperations()
.get(OptionKeys.INTERNAL_APPLICATION_IMAGE_PATH);
coreFS.maybeAddImagePath(launcher.getLocalResources(), imageURI);
CommandLineBuilder cli = new CommandLineBuilder();
String heap = appComponent.getOption(RoleKeys.JVM_HEAP, DEFAULT_JVM_HEAP);
if (SliderUtils.isSet(heap)) {
String adjustedHeap = SliderUtils.translateTrailingHeapUnit(heap);
launcher.setEnv(HBASE_HEAPSIZE, adjustedHeap);
}
String gcOpts = appComponent.getOption(RoleKeys.GC_OPTS, DEFAULT_GC_OPTS);
if (SliderUtils.isSet(gcOpts)) {
launcher.setEnv(HBASE_GC_OPTS, gcOpts);
}
//this must stay relative if it is an image
cli.add(providerUtils.buildPathToScript(
instanceDefinition,
"bin",
HBASE_SCRIPT));
//config dir is relative to the generated file
cli.add(ARG_CONFIG);
cli.add("$PROPAGATED_CONFDIR");
String roleCommand;
String logfile;
//now look at the role
switch (role) {
case ROLE_WORKER:
//role is region server
roleCommand = REGION_SERVER;
logfile = "/region-server.txt";
break;
case ROLE_MASTER:
roleCommand = MASTER;
logfile = "/master.txt";
break;
default:
throw new SliderInternalStateException("Cannot start role %s", role);
}
cli.add(roleCommand);
cli.add(ACTION_START);
//log details
cli.addOutAndErrFiles(logfile, null);
launcher.addCommand(cli.build());
}
@Override
public void applyInitialRegistryDefinitions(URL web,
ServiceInstanceData instanceData) throws
IOException {
super.applyInitialRegistryDefinitions(web, instanceData);
}
@Override
protected void serviceStart() throws Exception {
registerHBaseServiceEntry();
super.serviceStart();
}
private void registerHBaseServiceEntry() throws IOException {
String name = amState.getApplicationName() ;
// name += ".hbase";
ServiceInstanceData instanceData = new ServiceInstanceData(name,
HBASE_SERVICE_TYPE);
log.info("registering {}/{}", name, HBASE_SERVICE_TYPE );
PublishedConfiguration publishedSite =
new PublishedConfiguration("HBase site", siteConf);
PublishedConfigSet configSet =
amState.getOrCreatePublishedConfigSet(HBASE_SERVICE_TYPE);
instanceData.externalView.configurationsURL = SliderUtils.appendToURL(
amWebAPI.toExternalForm(), SLIDER_PATH_PUBLISHER, HBASE_SERVICE_TYPE);
configSet.put(HBASE_SITE_PUBLISHED_CONFIG, publishedSite);
registry.registerServiceInstance(instanceData, null);
}
/**
* Run this service
*
*
* @param instanceDefinition component description
* @param confDir local dir with the config
* @param env environment variables above those generated by
* @param execInProgress callback for the event notification
* @throws IOException IO problems
* @throws SliderException anything internal
*/
@Override
public boolean exec(AggregateConf instanceDefinition,
File confDir,
Map<String, String> env,
EventCallback execInProgress) throws
IOException,
SliderException {
return false;
}
/**
* This is a validation of the application configuration on the AM.
* Here is where things like the existence of keytabs and other
* not-seen-client-side properties can be tested, before
* the actual process is spawned.
* @param instanceDefinition clusterSpecification
* @param confDir configuration directory
* @param secure flag to indicate that secure mode checks must exist
* @throws IOException IO problemsn
* @throws SliderException any failure
*/
@Override
public void validateApplicationConfiguration(AggregateConf instanceDefinition,
File confDir,
boolean secure
) throws IOException,
SliderException {
String siteXMLFilename = SITE_XML;
File siteXML = new File(confDir, siteXMLFilename);
if (!siteXML.exists()) {
throw new BadCommandArgumentsException(
"Configuration directory %s doesn't contain %s - listing is %s",
confDir, siteXMLFilename, SliderUtils.listDir(confDir));
}
//now read it in
siteConf = ConfigHelper.loadConfFromFile(siteXML);
//look in the site spec to see that it is OK
clientProvider.validateHBaseSiteXML(siteConf, secure, siteXMLFilename);
if (secure) {
//secure mode: take a look at the keytab of master and RS
SliderUtils.verifyKeytabExists(siteConf,
HBaseConfigFileOptions.KEY_MASTER_KERBEROS_KEYTAB);
SliderUtils.verifyKeytabExists(siteConf,
HBaseConfigFileOptions.KEY_REGIONSERVER_KERBEROS_KEYTAB);
}
}
/**
* Build the provider status, can be empty
* @return the provider status - map of entries to add to the info section
*/
public Map<String, String> buildProviderStatus() {
Map<String, String> stats = new HashMap<>();
return stats;
}
@Override
public Map<String, String> buildMonitorDetails(ClusterDescription clusterDesc) {
Map<String, String> details = super.buildMonitorDetails(clusterDesc);
details.put("Active HBase Master (RPC): "
+ getInfoAvoidingNull(clusterDesc, StatusKeys.INFO_MASTER_ADDRESS),"");
return details;
}
@Override
public RegistrationResponse handleRegistration(Register registration) {
// dummy impl
RegistrationResponse response = new RegistrationResponse();
response.setResponseStatus(RegistrationStatus.OK);
return response;
}
@Override
public HeartBeatResponse handleHeartBeat(HeartBeat heartBeat) {
// dummy impl
long id = heartBeat.getResponseId();
HeartBeatResponse response = new HeartBeatResponse();
response.setResponseId(id + 1L);
return response;
}
}