/* * Copyright 2011-2012 the original author or authors. * * 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 org.springframework.xd.shell.hadoop; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.mapreduce.JobSubmissionFiles; import org.apache.hadoop.util.GenericOptionsParser; import org.apache.hadoop.util.VersionInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.data.hadoop.configuration.ConfigurationUtils; import org.springframework.shell.core.CommandMarker; import org.springframework.shell.core.ExecutionProcessor; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; import org.springframework.shell.event.ParseResult; import org.springframework.stereotype.Component; import org.springframework.util.Assert; /** * Command for configuring the global Hadoop {@link Configuration} object used by other components. Modeled after * {@link GenericOptionsParser} (for usability reasons). * * @author Costin Leau */ @Component public class ConfigurationCommands implements ApplicationEventPublisherAware, CommandMarker, ExecutionProcessor { // Ugly hack to make Hadoop work on Windows // placed here since these commands will be always enabled // the static block is used to execute this only once - probably in time it'll be more configurable static { // do the assignment only on Windows systems if (System.getProperty("os.name").startsWith("Windows")) { // 0655 = -rwxr-xr-x JobSubmissionFiles.JOB_DIR_PERMISSION.fromShort((short) 0655); JobSubmissionFiles.JOB_FILE_PERMISSION.fromShort((short) 0655); } } private static final String PREFIX = "hadoop config "; @Autowired private Configuration hadoopConfiguration; private ApplicationEventPublisher applicationEventPublisher; @CliCommand(value = { PREFIX + "load" }, help = "Loads the Hadoop configuration from the given resource") public String loadConfiguration( @CliOption(key = { "", "location" }, mandatory = true, help = "configuration location (can be a URL)") String location) { hadoopConfiguration.addResource(location); hadoopConfiguration.size(); return listProps(); } @CliCommand(value = { PREFIX + "props set" }, help = "Sets the value for the given Hadoop property") public void setProperty( @CliOption(key = { "", "property" }, mandatory = true, help = "what to set, in the form <name=value>") String property) { int i = property.indexOf("="); Assert.isTrue(i >= 0, "invalid format"); String name = property.substring(0, i); Assert.hasText(name, "a valid name is required"); String value = property.substring(i + 1); hadoopConfiguration.set(name, value); } @CliCommand(value = { PREFIX + "props get" }, help = "Returns the value of the given Hadoop property") public String getProperty(@CliOption(key = { "", "key" }, mandatory = true, help = "property name") String name) { return hadoopConfiguration.get(name); } @CliCommand(value = { PREFIX + "props list" }, help = "Returns (all) the Hadoop properties") public String listProps() { return ConfigurationUtils.asProperties(hadoopConfiguration).toString(); } @CliCommand(value = { PREFIX + "fs" }, help = "Sets the Hadoop namenode") public void setFs( @CliOption(key = { "", "namenode" }, mandatory = true, help = "namenode URL - can be file:///|hdfs://<namenode>:<port>|webhdfs://<namenode>:<port>") String namenode) { FileSystem.setDefaultUri(hadoopConfiguration, namenode); } @CliCommand(value = { PREFIX + "info" }, help = "Returns basic info about the Hadoop configuration") public String info() { StringBuilder sb = new StringBuilder(); sb.append("Hadoop ["); sb.append(VersionInfo.getVersion()); sb.append(" rev."); sb.append(VersionInfo.getRevision()); sb.append("]"); sb.append("[fs="); String fs = hadoopConfiguration.get("fs.defaultFS"); if (fs != null && fs.length() > 0) { sb.append(fs); } sb.append("]"); // TODO: potentially add a check to see whether HDFS is running return sb.toString(); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } @Override public ParseResult beforeInvocation(ParseResult invocationContext) { return invocationContext; } @Override public void afterReturningInvocation(ParseResult invocationContext, Object result) { String name = invocationContext.getMethod().getName(); if (name.startsWith("load") || name.startsWith("set")) { publishChange(); } } @Override public void afterThrowingInvocation(ParseResult invocationContext, Throwable thrown) { // no-op } private void publishChange() { applicationEventPublisher.publishEvent(new ConfigurationModifiedEvent(hadoopConfiguration)); } }