/** * 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.falcon.resource.admin; import org.apache.commons.lang3.StringUtils; import org.apache.falcon.FalconWebException; import org.apache.falcon.security.CurrentUser; import org.apache.falcon.security.SecurityUtil; import org.apache.falcon.util.BuildProperties; import org.apache.falcon.util.DeploymentProperties; import org.apache.falcon.util.RuntimeProperties; import org.apache.falcon.util.StartupProperties; import org.apache.hadoop.util.VersionInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; /** * Jersey Resource for admin operations. */ @Path("admin") public class AdminResource { public static final String SAFEMODE = "safemode"; private static final Logger LOG = LoggerFactory.getLogger(AdminResource.class); /** * Get stack trace of the falcon server. * @return Stack trace of the server. */ @GET @Path("stack") @Produces(MediaType.TEXT_PLAIN) public String getThreadDump() { ThreadGroup topThreadGroup = Thread.currentThread().getThreadGroup(); while (topThreadGroup.getParent() != null) { topThreadGroup = topThreadGroup.getParent(); } Thread[] threads = new Thread[topThreadGroup.activeCount()]; int nr = topThreadGroup.enumerate(threads); StringBuilder builder = new StringBuilder(); for (int i = 0; i < nr; i++) { builder.append(threads[i].getName()).append("\nState: "). append(threads[i].getState()).append("\n"); String stackTrace = StringUtils.join(threads[i].getStackTrace(), "\n"); builder.append(stackTrace); } return builder.toString(); } private PropertyList version; /** * Get version of the falcon server. * @return Version of the server. */ @GET @Path("version") @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) public PropertyList getVersion() { if (version == null) { List<Property> props = new ArrayList<Property>(); Property property = new Property(); property.key = "Version"; property.value = BuildProperties.get().getProperty("build.version"); props.add(property); property = new Property(); property.key = "Mode"; property.value = DeploymentProperties.get().getProperty("deploy.mode"); props.add(property); property = new Property(); property.key = "Hadoop"; property.value = VersionInfo.getVersion() + "-r" + VersionInfo.getRevision(); props.add(property); property = new Property(); property.key = "authentication"; property.value = StartupProperties.get().getProperty("falcon.authentication.type", "simple"); props.add(property); property = new Property(); property.key = SAFEMODE; property.value = StartupProperties.get().getProperty(StartupProperties.SAFEMODE_PROPERTY, "false"); props.add(property); version = new PropertyList(); version.properties = props; } return version; } /** * Set safemode for falcon server. * * @param mode Set safemode to true/false based on mode. * @return Configuration information of the server. */ @GET @Path("setSafeMode/{mode}") @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) public String setSafeMode(@PathParam("mode") String mode) { LOG.info("Setting falcon server safemode property to: {}", mode); try { if ("true".equalsIgnoreCase(mode)) { StartupProperties.createSafemodeFile(); } else if ("false".equalsIgnoreCase(mode)) { StartupProperties.deleteSafemodeFile(); } else { LOG.error("Bad request, Invalid value for setsafemode : {}", mode); throw FalconWebException.newAPIException("Invalid value \"" + mode + "\" provided for safemode.", Response.Status.BAD_REQUEST); } } catch (IOException e) { LOG.error("Unable to manage safemode file in Falcon Server {} ", e.getMessage()); throw FalconWebException.newAPIException(e.getMessage(), Response.Status.BAD_REQUEST); } return StartupProperties.get().getProperty(StartupProperties.SAFEMODE_PROPERTY, "false"); } /** * Get configuration information of the falcon server. * @param type config-type can be build, deploy, startup or runtime * @return Configuration information of the server. */ @GET @Path("config/{type}") @Produces({MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) public PropertyList getVersion(@PathParam("type") String type) { if ("build".equals(type)) { return getProperties(BuildProperties.get()); } else if ("deploy".equals(type)) { return getProperties(DeploymentProperties.get()); } else if ("startup".equals(type)) { return getProperties(StartupProperties.get()); } else if ("runtime".equals(type)) { return getProperties(RuntimeProperties.get()); } else { return null; } } private PropertyList getProperties(Properties properties) { List<Property> props = new ArrayList<Property>(); for (Object key : properties.keySet()) { Property property = new Property(); property.key = key.toString(); property.value = properties.getProperty(key.toString()); props.add(property); } PropertyList propertyList = new PropertyList(); propertyList.properties = props; return propertyList; } //SUSPEND CHECKSTYLE CHECK VisibilityModifierCheck /** * Class for property. */ @XmlRootElement(name = "property") @XmlAccessorType(XmlAccessType.FIELD) @edu.umd.cs.findbugs.annotations.SuppressWarnings({"URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"}) public static class Property { public String key; public String value; } //RESUME CHECKSTYLE CHECK VisibilityModifierCheck //SUSPEND CHECKSTYLE CHECK VisibilityModifierCheck /** * Class for list of Properties. */ @XmlRootElement(name = "properties") @XmlAccessorType(XmlAccessType.FIELD) @edu.umd.cs.findbugs.annotations.SuppressWarnings({"URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD"}) public static class PropertyList { public List<Property> properties; } //RESUME CHECKSTYLE CHECK VisibilityModifierCheck @GET @Path("clearuser") @Produces(MediaType.TEXT_PLAIN) public String clearUser(@Context HttpServletResponse response) { if (!SecurityUtil.isSecurityEnabled()) { Cookie cookie = new Cookie("hadoop.auth", null); cookie.setPath("/"); cookie.setMaxAge(0); cookie.setSecure(false); response.addCookie(cookie); } // Else, Do not checkin User, security is handled via Kerberos. return "ok"; } @GET @Path("getuser") @Produces(MediaType.TEXT_PLAIN) public String getAuthenticatedUser() { String user; try { if (SecurityUtil.isSecurityEnabled()) { user = CurrentUser.getAuthenticatedUser(); } else { user = CurrentUser.getUser(); } } catch (IllegalStateException ile) { user = ""; } return user; } }