You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by ji...@apache.org on 2016/12/07 21:10:31 UTC
[31/76] [abbrv] hadoop git commit: YARN-5461. Initial code ported
from slider-core module. (jianhe)
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java
new file mode 100644
index 0000000..30f6ba9
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/SliderClientAPI.java
@@ -0,0 +1,368 @@
+/*
+ * 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.client;
+
+import org.apache.hadoop.registry.client.api.RegistryOperations;
+import org.apache.hadoop.service.Service;
+import org.apache.hadoop.yarn.api.records.ApplicationReport;
+import org.apache.hadoop.yarn.api.records.YarnApplicationState;
+import org.apache.hadoop.yarn.exceptions.YarnException;
+import org.apache.slider.api.types.NodeInformationList;
+import org.apache.slider.api.types.SliderInstanceDescription;
+import org.apache.slider.common.params.AbstractClusterBuildingActionArgs;
+import org.apache.slider.common.params.ActionAMSuicideArgs;
+import org.apache.slider.common.params.ActionClientArgs;
+import org.apache.slider.common.params.ActionDependencyArgs;
+import org.apache.slider.common.params.ActionDestroyArgs;
+import org.apache.slider.common.params.ActionDiagnosticArgs;
+import org.apache.slider.common.params.ActionEchoArgs;
+import org.apache.slider.common.params.ActionFlexArgs;
+import org.apache.slider.common.params.ActionFreezeArgs;
+import org.apache.slider.common.params.ActionInstallKeytabArgs;
+import org.apache.slider.common.params.ActionInstallPackageArgs;
+import org.apache.slider.common.params.ActionKeytabArgs;
+import org.apache.slider.common.params.ActionNodesArgs;
+import org.apache.slider.common.params.ActionPackageArgs;
+import org.apache.slider.common.params.ActionKillContainerArgs;
+import org.apache.slider.common.params.ActionListArgs;
+import org.apache.slider.common.params.ActionRegistryArgs;
+import org.apache.slider.common.params.ActionResolveArgs;
+import org.apache.slider.common.params.ActionResourceArgs;
+import org.apache.slider.common.params.ActionStatusArgs;
+import org.apache.slider.common.params.ActionThawArgs;
+import org.apache.slider.common.params.ActionUpgradeArgs;
+import org.apache.slider.core.exceptions.BadCommandArgumentsException;
+import org.apache.slider.core.exceptions.SliderException;
+import org.apache.slider.providers.AbstractClientProvider;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Interface of those method calls in the slider API that are intended
+ * for direct public invocation.
+ * <p>
+ * Stability: evolving
+ */
+public interface SliderClientAPI extends Service {
+ /**
+ * Destroy a cluster. There's two race conditions here
+ * #1 the cluster is started between verifying that there are no live
+ * clusters of that name.
+ */
+ int actionDestroy(String clustername, ActionDestroyArgs destroyArgs)
+ throws YarnException, IOException;
+
+ int actionDestroy(String clustername) throws YarnException,
+ IOException;
+
+ /**
+ * AM to commit an asynchronous suicide
+ */
+ int actionAmSuicide(String clustername,
+ ActionAMSuicideArgs args) throws YarnException, IOException;
+
+ /**
+ * Get the provider for this cluster
+ * @param provider the name of the provider
+ * @return the provider instance
+ * @throws SliderException problems building the provider
+ */
+ AbstractClientProvider createClientProvider(String provider)
+ throws SliderException;
+
+ /**
+ * Build up the cluster specification/directory
+ *
+ * @param clustername cluster name
+ * @param buildInfo the arguments needed to build the cluster
+ * @throws YarnException Yarn problems
+ * @throws IOException other problems
+ * @throws BadCommandArgumentsException bad arguments.
+ */
+ int actionBuild(String clustername,
+ AbstractClusterBuildingActionArgs buildInfo) throws YarnException, IOException;
+
+ /**
+ * Upload keytab to a designated sub-directory of the user home directory
+ *
+ * @param installKeytabInfo the arguments needed to upload the keytab
+ * @throws YarnException Yarn problems
+ * @throws IOException other problems
+ * @throws BadCommandArgumentsException bad arguments.
+ * @deprecated use #actionKeytab
+ */
+ int actionInstallKeytab(ActionInstallKeytabArgs installKeytabInfo)
+ throws YarnException, IOException;
+
+ /**
+ * Manage keytabs leveraged by slider
+ *
+ * @param keytabInfo the arguments needed to manage the keytab
+ * @throws YarnException Yarn problems
+ * @throws IOException other problems
+ * @throws BadCommandArgumentsException bad arguments.
+ */
+ int actionKeytab(ActionKeytabArgs keytabInfo)
+ throws YarnException, IOException;
+
+ /**
+ * Upload application package to user home directory
+ *
+ * @param installPkgInfo the arguments needed to upload the package
+ * @throws YarnException Yarn problems
+ * @throws IOException other problems
+ * @throws BadCommandArgumentsException bad arguments.
+ */
+ int actionInstallPkg(ActionInstallPackageArgs installPkgInfo)
+ throws YarnException, IOException;
+
+ /**
+ * Manage file resources leveraged by slider
+ *
+ * @param resourceInfo the arguments needed to manage the resource
+ * @throws YarnException Yarn problems
+ * @throws IOException other problems
+ * @throws BadCommandArgumentsException bad arguments.
+ */
+ int actionResource(ActionResourceArgs resourceInfo)
+ throws YarnException, IOException;
+
+ /**
+ * Perform client operations such as install or configure
+ *
+ * @param clientInfo the arguments needed for client operations
+ *
+ * @throws SliderException bad arguments.
+ * @throws IOException problems related to package and destination folders
+ */
+ int actionClient(ActionClientArgs clientInfo)
+ throws IOException, YarnException;
+
+ /**
+ * Managing slider application package
+ *
+ * @param pkgInfo the arguments needed to upload, delete or list the package
+ * @throws YarnException Yarn problems
+ * @throws IOException other problems
+ * @throws BadCommandArgumentsException bad arguments.
+ */
+ int actionPackage(ActionPackageArgs pkgInfo)
+ throws YarnException, IOException;
+
+ /**
+ * Update the cluster specification
+ *
+ * @param clustername cluster name
+ * @param buildInfo the arguments needed to update the cluster
+ * @throws YarnException Yarn problems
+ * @throws IOException other problems
+ */
+ int actionUpdate(String clustername,
+ AbstractClusterBuildingActionArgs buildInfo)
+ throws YarnException, IOException;
+
+ /**
+ * Upgrade the cluster with a newer version of the application
+ *
+ * @param clustername cluster name
+ * @param buildInfo the arguments needed to upgrade the cluster
+ * @throws YarnException Yarn problems
+ * @throws IOException other problems
+ */
+ int actionUpgrade(String clustername,
+ ActionUpgradeArgs buildInfo)
+ throws YarnException, IOException;
+
+ /**
+ * Get the report of a this application
+ * @return the app report or null if it could not be found.
+ * @throws IOException
+ * @throws YarnException
+ */
+ ApplicationReport getApplicationReport()
+ throws IOException, YarnException;
+
+ /**
+ * Kill the submitted application via YARN
+ * @throws YarnException
+ * @throws IOException
+ */
+ boolean forceKillApplication(String reason)
+ throws YarnException, IOException;
+
+ /**
+ * Implement the list action: list all nodes
+ * @return exit code of 0 if a list was created
+ */
+ int actionList(String clustername, ActionListArgs args) throws IOException, YarnException;
+
+ /**
+ * Enumerate slider instances for the current user, and the
+ * most recent app report, where available.
+ * @param listOnlyInState boolean to indicate that the instances should
+ * only include those in a YARN state
+ * <code> minAppState <= currentState <= maxAppState </code>
+ *
+ * @param minAppState minimum application state to include in enumeration.
+ * @param maxAppState maximum application state to include
+ * @return a map of application instance name to description
+ * @throws IOException Any IO problem
+ * @throws YarnException YARN problems
+ */
+ Map<String, SliderInstanceDescription> enumSliderInstances(
+ boolean listOnlyInState,
+ YarnApplicationState minAppState,
+ YarnApplicationState maxAppState)
+ throws IOException, YarnException;
+
+ /**
+ * Implement the islive action: probe for a cluster of the given name existing
+ * @return exit code
+ */
+ int actionFlex(String name, ActionFlexArgs args) throws YarnException, IOException;
+
+ /**
+ * Test for a cluster existing probe for a cluster of the given name existing
+ * in the filesystem. If the live param is set, it must be a live cluster
+ * @return exit code
+ */
+ int actionExists(String name, boolean checkLive) throws YarnException, IOException;
+
+ /**
+ * Kill a specific container of the cluster
+ * @param name cluster name
+ * @param args arguments
+ * @return exit code
+ * @throws YarnException
+ * @throws IOException
+ */
+ int actionKillContainer(String name, ActionKillContainerArgs args)
+ throws YarnException, IOException;
+
+ /**
+ * Echo operation (not currently wired up to command line)
+ * @param name cluster name
+ * @param args arguments
+ * @return the echoed text
+ * @throws YarnException
+ * @throws IOException
+ */
+ String actionEcho(String name, ActionEchoArgs args)
+ throws YarnException, IOException;
+
+ /**
+ * Status operation
+ *
+ * @param clustername cluster name
+ * @param statusArgs status arguments
+ * @return 0 -for success, else an exception is thrown
+ * @throws YarnException
+ * @throws IOException
+ */
+ int actionStatus(String clustername, ActionStatusArgs statusArgs)
+ throws YarnException, IOException;
+
+ /**
+ * Version Details
+ * @return exit code
+ */
+ int actionVersion();
+
+ /**
+ * Stop the cluster
+ *
+ * @param clustername cluster name
+ * @param freezeArgs arguments to the stop
+ * @return EXIT_SUCCESS if the cluster was not running by the end of the operation
+ */
+ int actionFreeze(String clustername, ActionFreezeArgs freezeArgs)
+ throws YarnException, IOException;
+
+ /**
+ * Restore a cluster
+ */
+ int actionThaw(String clustername, ActionThawArgs thaw) throws YarnException, IOException;
+
+ /**
+ * Registry operation
+ *
+ * @param args registry Arguments
+ * @return 0 for success, -1 for some issues that aren't errors, just failures
+ * to retrieve information (e.g. no configurations for that entry)
+ * @throws YarnException YARN problems
+ * @throws IOException Network or other problems
+ */
+ int actionResolve(ActionResolveArgs args)
+ throws YarnException, IOException;
+
+ /**
+ * Registry operation
+ *
+ * @param registryArgs registry Arguments
+ * @return 0 for success, -1 for some issues that aren't errors, just failures
+ * to retrieve information (e.g. no configurations for that entry)
+ * @throws YarnException YARN problems
+ * @throws IOException Network or other problems
+ */
+ int actionRegistry(ActionRegistryArgs registryArgs)
+ throws YarnException, IOException;
+
+ /**
+ * diagnostic operation
+ *
+ * @param diagnosticArgs diagnostic Arguments
+ * @return 0 for success, -1 for some issues that aren't errors, just
+ * failures to retrieve information (e.g. no application name
+ * specified)
+ * @throws YarnException YARN problems
+ * @throws IOException Network or other problems
+ */
+ int actionDiagnostic(ActionDiagnosticArgs diagnosticArgs);
+
+ /**
+ * Get the registry binding. As this may start the registry, it can take time
+ * and fail
+ * @return the registry
+ */
+ RegistryOperations getRegistryOperations()
+ throws SliderException, IOException;
+
+ /**
+ * Upload all Slider AM and agent dependency libraries to HDFS, so that they
+ * do not need to be uploaded with every create call. This operation is
+ * Slider version specific. So it needs to be invoked for every single
+ * version of slider/slider-client.
+ *
+ * @throws SliderException
+ * @throws IOException
+ */
+ int actionDependency(ActionDependencyArgs dependencyArgs) throws IOException,
+ YarnException;
+
+ /**
+ * List the nodes
+ * @param args
+ * @return
+ * @throws YarnException
+ * @throws IOException
+ */
+ NodeInformationList listYarnClusterNodes(ActionNodesArgs args)
+ throws YarnException, IOException;
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java
new file mode 100644
index 0000000..d471cdb
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/SliderYarnClientImpl.java
@@ -0,0 +1,410 @@
+/*
+ * 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.client;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.yarn.api.ApplicationClientProtocol;
+import org.apache.hadoop.yarn.api.protocolrecords.KillApplicationRequest;
+import org.apache.hadoop.yarn.api.protocolrecords.KillApplicationResponse;
+import org.apache.hadoop.yarn.api.records.ApplicationId;
+import org.apache.hadoop.yarn.api.records.ApplicationReport;
+import org.apache.hadoop.yarn.api.records.NodeReport;
+import org.apache.hadoop.yarn.api.records.NodeState;
+import org.apache.hadoop.yarn.api.records.YarnApplicationState;
+import org.apache.hadoop.yarn.client.api.impl.YarnClientImpl;
+import org.apache.hadoop.yarn.conf.YarnConfiguration;
+import org.apache.hadoop.yarn.exceptions.YarnException;
+import org.apache.hadoop.yarn.util.ConverterUtils;
+import org.apache.hadoop.yarn.util.Records;
+import org.apache.slider.api.types.NodeInformation;
+import org.apache.slider.api.types.NodeInformationList;
+import org.apache.slider.common.SliderKeys;
+import org.apache.slider.common.params.ActionNodesArgs;
+import org.apache.slider.common.tools.CoreFileSystem;
+import org.apache.slider.common.tools.Duration;
+import org.apache.slider.common.tools.SliderFileSystem;
+import org.apache.slider.common.tools.SliderUtils;
+import org.apache.slider.core.exceptions.BadCommandArgumentsException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.BindException;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A class that extends visibility to some of the YarnClientImpl
+ * members and data structures, and factors out pure-YARN operations
+ * from the slider entry point service
+ */
+public class SliderYarnClientImpl extends YarnClientImpl {
+ protected static final Logger log = LoggerFactory.getLogger(SliderYarnClientImpl.class);
+
+ /**
+ * Keyword to use in the {@link #emergencyForceKill(String)}
+ * operation to force kill <i>all</i> application instances belonging
+ * to a specific user
+ */
+ public static final String KILL_ALL = "all";
+
+ @Override
+ protected void serviceInit(Configuration conf) throws Exception {
+ InetSocketAddress clientRpcAddress = SliderUtils.getRmAddress(conf);
+ if (!SliderUtils.isAddressDefined(clientRpcAddress)) {
+ // address isn't known; fail fast
+ throw new BindException("Invalid " + YarnConfiguration.RM_ADDRESS
+ + " value:" + conf.get(YarnConfiguration.RM_ADDRESS)
+ + " - see https://wiki.apache.org/hadoop/UnsetHostnameOrPort");
+ }
+ super.serviceInit(conf);
+ }
+
+ /**
+ * Get the RM Client RPC interface
+ * @return an RPC interface valid after initialization and authentication
+ */
+ public ApplicationClientProtocol getRmClient() {
+ return rmClient;
+ }
+
+ /**
+ * List Slider <i>running</i>instances belonging to a specific user.
+ * @deprecated use {@link #listDeployedInstances(String)}
+ * @param user user: "" means all users
+ * @return a possibly empty list of Slider AMs
+ */
+ public List<ApplicationReport> listInstances(String user)
+ throws YarnException, IOException {
+ return listDeployedInstances(user);
+ }
+
+ /**
+ * List Slider <i>deployed</i>instances belonging to a specific user.
+ * <p>
+ * Deployed means: known about in the YARN cluster; it will include
+ * any that are in the failed/finished state, as well as those queued
+ * for starting.
+ * @param user user: "" means all users
+ * @return a possibly empty list of Slider AMs
+ */
+ public List<ApplicationReport> listDeployedInstances(String user)
+ throws YarnException, IOException {
+ Preconditions.checkArgument(user != null, "Null User");
+ Set<String> types = new HashSet<>(1);
+ types.add(SliderKeys.APP_TYPE);
+ List<ApplicationReport> allApps = getApplications(types);
+ List<ApplicationReport> results = new ArrayList<>();
+ for (ApplicationReport report : allApps) {
+ if (StringUtils.isEmpty(user) || user.equals(report.getUser())) {
+ results.add(report);
+ }
+ }
+ return results;
+ }
+
+ /**
+ * find all instances of a specific app -if there is more than one in the
+ * YARN cluster,
+ * this returns them all
+ * @param user user; use "" for all users
+ * @param appname application name
+ * @return the list of all matching application instances
+ */
+ public List<ApplicationReport> findAllInstances(String user,
+ String appname)
+ throws IOException, YarnException {
+ Preconditions.checkArgument(appname != null, "Null application name");
+
+ List<ApplicationReport> instances = listDeployedInstances(user);
+ List<ApplicationReport> results =
+ new ArrayList<>(instances.size());
+ for (ApplicationReport report : instances) {
+ if (report.getName().equals(appname)) {
+ results.add(report);
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Helper method to determine if a cluster application is running -or
+ * is earlier in the lifecycle
+ * @param app application report
+ * @return true if the application is considered live
+ */
+ public boolean isApplicationLive(ApplicationReport app) {
+ Preconditions.checkArgument(app != null, "Null app report");
+
+ return app.getYarnApplicationState().ordinal() <= YarnApplicationState.RUNNING.ordinal();
+ }
+
+
+ /**
+ * Kill a running application
+ * @param applicationId app Id
+ * @param reason reason: reason for log
+ * @return the response
+ * @throws YarnException YARN problems
+ * @throws IOException IO problems
+ */
+ public KillApplicationResponse killRunningApplication(ApplicationId applicationId,
+ String reason)
+ throws YarnException, IOException {
+ Preconditions.checkArgument(applicationId != null, "Null application Id");
+ log.info("Killing application {} - {}", applicationId.getClusterTimestamp(),
+ reason);
+ KillApplicationRequest request =
+ Records.newRecord(KillApplicationRequest.class);
+ request.setApplicationId(applicationId);
+ return getRmClient().forceKillApplication(request);
+ }
+
+ private String getUsername() throws IOException {
+ return UserGroupInformation.getCurrentUser().getShortUserName();
+ }
+
+ /**
+ * Force kill a yarn application by ID. No niceties here
+ * @param applicationId app Id. "all" means "kill all instances of the current user
+ *
+ */
+ public void emergencyForceKill(String applicationId)
+ throws YarnException, IOException {
+
+ Preconditions.checkArgument(StringUtils.isNotEmpty(applicationId),
+ "Null/empty application Id");
+
+ if (KILL_ALL.equals(applicationId)) {
+ // user wants all instances killed
+ String user = getUsername();
+ log.info("Killing all applications belonging to {}", user);
+ Collection<ApplicationReport> instances = listDeployedInstances(user);
+ for (ApplicationReport instance : instances) {
+ if (isApplicationLive(instance)) {
+ ApplicationId appId = instance.getApplicationId();
+ log.info("Killing Application {}", appId);
+
+ killRunningApplication(appId, "forced kill");
+ }
+ }
+ } else {
+ ApplicationId appId = ConverterUtils.toApplicationId(applicationId);
+
+ log.info("Killing Application {}", applicationId);
+
+ killRunningApplication(appId, "forced kill");
+ }
+ }
+
+ /**
+ * Monitor the submitted application for reaching the requested state.
+ * Will also report if the app reaches a later state (failed, killed, etc)
+ * Kill application if duration!= null & time expires.
+ * @param appId Application Id of application to be monitored
+ * @param duration how long to wait -must be more than 0
+ * @param desiredState desired state.
+ * @return the application report -null on a timeout
+ * @throws YarnException
+ * @throws IOException
+ */
+ public ApplicationReport monitorAppToState(
+ ApplicationId appId, YarnApplicationState desiredState, Duration duration)
+ throws YarnException, IOException {
+
+ if (appId == null) {
+ throw new BadCommandArgumentsException("null application ID");
+ }
+ if (duration.limit <= 0) {
+ throw new BadCommandArgumentsException("Invalid monitoring duration");
+ }
+ log.debug("Waiting {} millis for app to reach state {} ",
+ duration.limit,
+ desiredState);
+ duration.start();
+ try {
+ while (true) {
+ // Get application report for the appId we are interested in
+
+ ApplicationReport r = getApplicationReport(appId);
+
+ log.debug("queried status is\n{}",
+ new SliderUtils.OnDemandReportStringifier(r));
+
+ YarnApplicationState state = r.getYarnApplicationState();
+ if (state.ordinal() >= desiredState.ordinal()) {
+ log.debug("App in desired state (or higher) :{}", state);
+ return r;
+ }
+ if (duration.getLimitExceeded()) {
+ log.debug(
+ "Wait limit of {} millis to get to state {}, exceeded; app status\n {}",
+ duration.limit,
+ desiredState,
+ new SliderUtils.OnDemandReportStringifier(r));
+ return null;
+ }
+
+ // sleep 1s.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ignored) {
+ log.debug("Thread sleep in monitoring loop interrupted");
+ }
+ }
+ } finally {
+ duration.close();
+ }
+ }
+
+ /**
+ * find all live instances of a specific app -if there is >1 in the cluster,
+ * this returns them all. State should be running or less
+ * @param user user
+ * @param appname application name
+ * @return the list of all matching application instances
+ */
+ public List<ApplicationReport> findAllLiveInstances(String user,
+ String appname) throws
+ YarnException,
+ IOException {
+ Preconditions.checkArgument(StringUtils.isNotEmpty(appname),
+ "Null/empty application name");
+ List<ApplicationReport> instances = listDeployedInstances(user);
+ List<ApplicationReport> results =
+ new ArrayList<ApplicationReport>(instances.size());
+ for (ApplicationReport app : instances) {
+ if (app.getName().equals(appname)
+ && isApplicationLive(app)) {
+ results.add(app);
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Find a cluster in the instance list; biased towards live instances
+ * @param instances list of instances
+ * @param appname application name
+ * @return the first found instance, else a failed/finished instance, or null
+ * if there are none of those
+ */
+ public ApplicationReport findClusterInInstanceList(List<ApplicationReport> instances,
+ String appname) {
+ Preconditions.checkArgument(instances != null, "Null instances list");
+ Preconditions.checkArgument(StringUtils.isNotEmpty(appname),
+ "Null/empty application name");
+ // sort by most recent
+ SliderUtils.sortApplicationsByMostRecent(instances);
+ ApplicationReport found = null;
+ for (ApplicationReport app : instances) {
+ if (app.getName().equals(appname)) {
+ if (isApplicationLive(app)) {
+ return app;
+ }
+ // set the found value if not set
+ found = found != null ? found : app;
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Find an app in the instance list in the desired state
+ * @param instances instance list
+ * @param appname application name
+ * @param desiredState yarn state desired
+ * @return the match or null for none
+ */
+ public ApplicationReport findAppInInstanceList(List<ApplicationReport> instances,
+ String appname,
+ YarnApplicationState desiredState) {
+ Preconditions.checkArgument(instances != null, "Null instances list");
+ Preconditions.checkArgument(StringUtils.isNotEmpty(appname),
+ "Null/empty application name");
+ Preconditions.checkArgument(desiredState != null, "Null desiredState");
+ log.debug("Searching {} records for instance name {} in state '{}'",
+ instances.size(), appname, desiredState);
+ for (ApplicationReport app : instances) {
+ if (app.getName().equals(appname)) {
+
+ YarnApplicationState appstate =
+ app.getYarnApplicationState();
+ log.debug("app ID {} is in state {}", app.getApplicationId(), appstate);
+ if (appstate.equals(desiredState)) {
+ log.debug("match");
+ return app;
+ }
+ }
+ }
+ // nothing found in desired state
+ log.debug("No match");
+ return null;
+ }
+
+ /**
+ * List the nodes in the cluster, possibly filtering by node state or label.
+ *
+ * @param label label to filter by -or "" for any
+ * @param live flag to request running nodes only
+ * @return a possibly empty list of nodes in the cluster
+ * @throws IOException IO problems
+ * @throws YarnException YARN problems
+ */
+ public NodeInformationList listNodes(String label, boolean live)
+ throws IOException, YarnException {
+ Preconditions.checkArgument(label != null, "null label");
+ NodeState[] states;
+ if (live) {
+ states = new NodeState[1];
+ states[0] = NodeState.RUNNING;
+ } else {
+ states = new NodeState[0];
+ }
+ List<NodeReport> reports = getNodeReports(states);
+ NodeInformationList results = new NodeInformationList(reports.size());
+ for (NodeReport report : reports) {
+ if (live && report.getNodeState() != NodeState.RUNNING) {
+ continue;
+ }
+ if (!label.isEmpty() && !report.getNodeLabels().contains(label)) {
+ continue;
+ }
+ // build node info from report
+ NodeInformation info = new NodeInformation();
+ info.hostname = report.getNodeId().getHost();
+ info.healthReport = report.getHealthReport();
+ info.httpAddress = report.getHttpAddress();
+ info.labels = SliderUtils.extractNodeLabel(report);
+ info.rackName = report.getRackName();
+ info.state = report.getNodeState().toString();
+ results.add(info);
+ }
+ return results;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/TokensOperation.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/TokensOperation.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/TokensOperation.java
new file mode 100644
index 0000000..9b9c141
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/TokensOperation.java
@@ -0,0 +1,109 @@
+/*
+ * 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.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.security.Credentials;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.yarn.client.api.impl.YarnClientImpl;
+import org.apache.hadoop.yarn.exceptions.YarnException;
+import org.apache.slider.common.params.ActionTokensArgs;
+import org.apache.slider.core.exceptions.BadClusterStateException;
+import org.apache.slider.core.exceptions.NotFoundException;
+import static org.apache.slider.core.launch.CredentialUtils.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+
+public class TokensOperation {
+
+ private static final Logger log = LoggerFactory.getLogger(TokensOperation.class);
+ public static final String E_INSECURE
+ = "Cluster is not secure -tokens cannot be acquired";
+ public static final String E_MISSING_SOURCE_FILE = "Missing source file: ";
+ public static final String E_NO_KEYTAB = "No keytab: ";
+
+ public int actionTokens(ActionTokensArgs args, FileSystem fs,
+ Configuration conf,
+ YarnClientImpl yarnClient)
+ throws IOException, YarnException {
+ Credentials credentials;
+ String footnote = "";
+ UserGroupInformation user = UserGroupInformation.getCurrentUser();
+ boolean isSecure = UserGroupInformation.isSecurityEnabled();
+ if (args.keytab != null) {
+ File keytab = args.keytab;
+ if (!keytab.isFile()) {
+ throw new NotFoundException(E_NO_KEYTAB + keytab.getAbsolutePath());
+ }
+ String principal = args.principal;
+ log.info("Logging in as {} from keytab {}", principal, keytab);
+ user = UserGroupInformation.loginUserFromKeytabAndReturnUGI(
+ principal, keytab.getCanonicalPath());
+ }
+ Credentials userCredentials = user.getCredentials();
+ File output = args.output;
+ if (output != null) {
+ if (!isSecure) {
+ throw new BadClusterStateException(E_INSECURE);
+ }
+ credentials = new Credentials(userCredentials);
+ // filesystem
+ addRMRenewableFSDelegationTokens(conf, fs, credentials);
+ addRMDelegationToken(yarnClient, credentials);
+ if (maybeAddTimelineToken(conf, credentials) != null) {
+ log.debug("Added timeline token");
+ }
+ saveTokens(output, credentials);
+ String filename = output.getCanonicalPath();
+ footnote = String.format("%d tokens saved to %s\n" +
+ "To use these in the environment:\n" +
+ "export %s=%s",
+ credentials.numberOfTokens(),
+ filename, UserGroupInformation.HADOOP_TOKEN_FILE_LOCATION, filename);
+ } else if (args.source != null) {
+ File source = args.source;
+ log.info("Reading credentials from file {}", source);
+ if (!source.isFile()) {
+ throw new NotFoundException( E_MISSING_SOURCE_FILE + source.getAbsolutePath());
+ }
+ credentials = Credentials.readTokenStorageFile(args.source, conf);
+ } else {
+ StringBuffer origin = new StringBuffer();
+ File file = locateEnvCredentials(System.getenv(), conf,
+ origin);
+ if (file != null) {
+ log.info("Credential Source {}", origin);
+ } else {
+ log.info("Credential source: logged in user");
+ }
+ credentials = userCredentials;
+ }
+ // list the tokens
+ log.info("\n{}", dumpTokens(credentials, "\n"));
+ if (!footnote.isEmpty()) {
+ log.info(footnote);
+ }
+ return 0;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/ipc/SliderApplicationIpcClient.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/ipc/SliderApplicationIpcClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/ipc/SliderApplicationIpcClient.java
new file mode 100644
index 0000000..a007326
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/ipc/SliderApplicationIpcClient.java
@@ -0,0 +1,245 @@
+/*
+ * 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.client.ipc;
+
+import com.google.common.base.Preconditions;
+import org.apache.slider.api.SliderClusterProtocol;
+import org.apache.slider.api.types.ApplicationLivenessInformation;
+import org.apache.slider.api.types.ComponentInformation;
+import org.apache.slider.api.types.ContainerInformation;
+import org.apache.slider.api.types.NodeInformation;
+import org.apache.slider.api.types.NodeInformationList;
+import org.apache.slider.api.types.PingInformation;
+import org.apache.slider.api.SliderApplicationApi;
+import org.apache.slider.core.conf.AggregateConf;
+import org.apache.slider.core.conf.ConfTree;
+import org.apache.slider.core.conf.ConfTreeOperations;
+import org.apache.slider.core.exceptions.NoSuchNodeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Implementation of the Slider RESTy Application API over IPC.
+ * <p>
+ * Operations are executed via the {@link SliderClusterOperations}
+ * instance passed in; raised exceptions may be converted into ones
+ * consistent with the REST API.
+ */
+public class SliderApplicationIpcClient implements SliderApplicationApi {
+
+ private static final Logger log =
+ LoggerFactory.getLogger(SliderApplicationIpcClient.class);
+
+ private final SliderClusterOperations operations;
+
+ public SliderApplicationIpcClient(SliderClusterOperations operations) {
+ Preconditions.checkArgument(operations != null, "null operations");
+ this.operations = operations;
+ }
+
+ /**
+ * Convert received (And potentially unmarshalled) local/remote
+ * exceptions into the equivalents in the REST API.
+ * Best effort.
+ * <p>
+ * If there is no translation, the original exception is returned.
+ * <p>
+ * If a new exception was created, it will have the message of the
+ * string value of the original exception, and that original
+ * exception will be the nested cause of this one
+ * @param exception IOException to convert
+ * @return an exception to throw
+ */
+ private IOException convert(IOException exception) {
+ IOException result = exception;
+ if (exception instanceof NoSuchNodeException) {
+ result = new FileNotFoundException(exception.toString());
+ result.initCause(exception);
+ } else {
+ // TODO: remap any other exceptions
+ }
+ return result;
+ }
+
+ public SliderApplicationIpcClient(SliderClusterProtocol proxy) {
+ this(new SliderClusterOperations(proxy));
+ }
+
+ @Override
+ public AggregateConf getDesiredModel() throws IOException {
+ try {
+ return operations.getModelDesired();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public ConfTreeOperations getDesiredAppconf() throws IOException {
+ try {
+ return operations.getModelDesiredAppconf();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public ConfTreeOperations getDesiredResources() throws IOException {
+ try {
+ return operations.getModelDesiredResources();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+
+ @Override
+ public void putDesiredResources(ConfTree updated) throws IOException {
+ try {
+ operations.flex(updated);
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+
+ @Override
+ public AggregateConf getResolvedModel() throws IOException {
+ try {
+ return operations.getModelResolved();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public ConfTreeOperations getResolvedAppconf() throws IOException {
+ try {
+ return operations.getModelResolvedAppconf();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public ConfTreeOperations getResolvedResources() throws IOException {
+ try {
+ return operations.getModelResolvedResources();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public ConfTreeOperations getLiveResources() throws IOException {
+ try {
+ return operations.getLiveResources();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public Map<String, ContainerInformation> enumContainers() throws IOException {
+ try {
+ return operations.enumContainers();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public ContainerInformation getContainer(String containerId) throws
+ IOException {
+ try {
+ return operations.getContainer(containerId);
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public Map<String, ComponentInformation> enumComponents() throws IOException {
+ try {
+ return operations.enumComponents();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public ComponentInformation getComponent(String componentName) throws IOException {
+ try {
+ return operations.getComponent(componentName);
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public NodeInformationList getLiveNodes() throws IOException {
+ try {
+ return operations.getLiveNodes();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public NodeInformation getLiveNode(String hostname) throws IOException {
+ try {
+ return operations.getLiveNode(hostname);
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public PingInformation ping(String text) throws IOException {
+ return null;
+ }
+
+ @Override
+ public void stop(String text) throws IOException {
+ try {
+ operations.stop(text);
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public ApplicationLivenessInformation getApplicationLiveness() throws
+ IOException {
+ try {
+ return operations.getApplicationLiveness();
+ } catch (IOException e) {
+ throw convert(e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "IPC implementation of SliderApplicationApi bonded to " + operations;
+ }
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/ipc/SliderClusterOperations.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/ipc/SliderClusterOperations.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/ipc/SliderClusterOperations.java
new file mode 100644
index 0000000..392f451
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/ipc/SliderClusterOperations.java
@@ -0,0 +1,529 @@
+/*
+ * 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.client.ipc;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import org.apache.hadoop.yarn.api.records.NodeReport;
+import org.apache.hadoop.yarn.api.records.NodeState;
+import org.apache.hadoop.yarn.exceptions.YarnException;
+import org.apache.slider.api.ClusterDescription;
+import org.apache.slider.api.ClusterNode;
+import org.apache.slider.api.SliderClusterProtocol;
+import org.apache.slider.api.StateValues;
+import org.apache.slider.api.proto.Messages;
+
+import static org.apache.slider.api.proto.RestTypeMarshalling.*;
+import org.apache.slider.api.types.ApplicationLivenessInformation;
+import org.apache.slider.api.types.ComponentInformation;
+import org.apache.slider.api.types.ContainerInformation;
+import org.apache.slider.api.types.NodeInformation;
+import org.apache.slider.api.types.NodeInformationList;
+import org.apache.slider.api.types.PingInformation;
+import org.apache.slider.common.tools.Duration;
+import org.apache.slider.common.tools.SliderUtils;
+import org.apache.slider.core.conf.AggregateConf;
+import org.apache.slider.core.conf.ConfTree;
+import org.apache.slider.core.conf.ConfTreeOperations;
+import org.apache.slider.core.exceptions.NoSuchNodeException;
+import org.apache.slider.core.exceptions.SliderException;
+import org.apache.slider.core.exceptions.WaitTimeoutException;
+import org.apache.slider.core.persist.ConfTreeSerDeser;
+import org.apache.slider.server.services.security.SecurityStore;
+import org.apache.slider.server.services.security.SignCertResponse;
+import org.codehaus.jackson.JsonParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Cluster operations at a slightly higher level than the RPC code
+ */
+public class SliderClusterOperations {
+ protected static final Logger
+ log = LoggerFactory.getLogger(SliderClusterOperations.class);
+
+ private final SliderClusterProtocol appMaster;
+ private static final Messages.EmptyPayloadProto EMPTY;
+ static {
+ EMPTY = Messages.EmptyPayloadProto.newBuilder().build();
+ }
+
+ public SliderClusterOperations(SliderClusterProtocol appMaster) {
+ this.appMaster = appMaster;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb =
+ new StringBuilder("SliderClusterOperations{");
+ sb.append("IPC binding=").append(appMaster);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ /**
+ * Get a node from the AM
+ * @param uuid uuid of node
+ * @return deserialized node
+ * @throws IOException IO problems
+ * @throws NoSuchNodeException if the node isn't found
+ */
+ public ClusterNode getNode(String uuid)
+ throws IOException, NoSuchNodeException, YarnException {
+ Messages.GetNodeRequestProto req =
+ Messages.GetNodeRequestProto.newBuilder().setUuid(uuid).build();
+ Messages.GetNodeResponseProto node = appMaster.getNode(req);
+ return ClusterNode.fromProtobuf(node.getClusterNode());
+ }
+
+ /**
+ * Unmarshall a list of nodes from a protobud response
+ * @param nodes node list
+ * @return possibly empty list of cluster nodes
+ * @throws IOException
+ */
+ public List<ClusterNode> convertNodeWireToClusterNodes(List<Messages.RoleInstanceState> nodes)
+ throws IOException {
+ List<ClusterNode> nodeList = new ArrayList<>(nodes.size());
+ for (Messages.RoleInstanceState node : nodes) {
+ nodeList.add(ClusterNode.fromProtobuf(node));
+ }
+ return nodeList;
+ }
+
+ /**
+ * Echo text (debug action)
+ * @param text text
+ * @return the text, echoed back
+ * @throws YarnException
+ * @throws IOException
+ */
+ public String echo(String text) throws YarnException, IOException {
+ Messages.EchoRequestProto.Builder builder =
+ Messages.EchoRequestProto.newBuilder();
+ builder.setText(text);
+ Messages.EchoRequestProto req = builder.build();
+ Messages.EchoResponseProto response = appMaster.echo(req);
+ return response.getText();
+ }
+
+
+ /**
+ * Connect to a live cluster and get its current state
+ * @return its description
+ */
+ public ClusterDescription getClusterDescription()
+ throws YarnException, IOException {
+
+ Messages.GetJSONClusterStatusRequestProto req =
+ Messages.GetJSONClusterStatusRequestProto.newBuilder().build();
+ Messages.GetJSONClusterStatusResponseProto resp =
+ appMaster.getJSONClusterStatus(req);
+ String statusJson = resp.getClusterSpec();
+ try {
+ return ClusterDescription.fromJson(statusJson);
+ } catch (JsonParseException e) {
+ log.error("Exception " + e + " parsing:\n" + statusJson, e);
+ throw e;
+ }
+ }
+
+ /**
+ * Get the AM instance definition.
+ * <p>
+ * See {@link SliderClusterProtocol#getInstanceDefinition(Messages.GetInstanceDefinitionRequestProto)}
+ * @return current slider AM aggregate definition
+ * @throws YarnException
+ * @throws IOException
+ */
+ public AggregateConf getInstanceDefinition()
+ throws YarnException, IOException {
+ Messages.GetInstanceDefinitionRequestProto.Builder builder =
+ Messages.GetInstanceDefinitionRequestProto.newBuilder();
+
+ Messages.GetInstanceDefinitionRequestProto request = builder.build();
+ Messages.GetInstanceDefinitionResponseProto response =
+ appMaster.getInstanceDefinition(request);
+
+ ConfTreeSerDeser confTreeSerDeser = new ConfTreeSerDeser();
+
+ ConfTree internal = confTreeSerDeser.fromJson(response.getInternal());
+ ConfTree resources = confTreeSerDeser.fromJson(response.getResources());
+ ConfTree app = confTreeSerDeser.fromJson(response.getApplication());
+ AggregateConf instanceDefinition =
+ new AggregateConf(resources, app, internal);
+ return instanceDefinition;
+ }
+ /**
+ * Kill a container
+ * @param id container ID
+ * @return a success flag
+ * @throws YarnException
+ * @throws IOException
+ */
+ public boolean killContainer(String id) throws
+ YarnException,
+ IOException {
+ Messages.KillContainerRequestProto.Builder builder =
+ Messages.KillContainerRequestProto.newBuilder();
+ builder.setId(id);
+ Messages.KillContainerRequestProto req = builder.build();
+ Messages.KillContainerResponseProto response = appMaster.killContainer(req);
+ return response.getSuccess();
+ }
+
+ /**
+ * List all node UUIDs in a role
+ * @param role role name or "" for all
+ * @return an array of UUID strings
+ * @throws IOException
+ * @throws YarnException
+ */
+ public String[] listNodeUUIDsByRole(String role) throws IOException, YarnException {
+ Collection<String> uuidList = innerListNodeUUIDSByRole(role);
+ String[] uuids = new String[uuidList.size()];
+ return uuidList.toArray(uuids);
+ }
+
+ public List<String> innerListNodeUUIDSByRole(String role) throws IOException, YarnException {
+ Messages.ListNodeUUIDsByRoleRequestProto req =
+ Messages.ListNodeUUIDsByRoleRequestProto
+ .newBuilder()
+ .setRole(role)
+ .build();
+ Messages.ListNodeUUIDsByRoleResponseProto resp = appMaster.listNodeUUIDsByRole(req);
+ return resp.getUuidList();
+ }
+
+ /**
+ * List all nodes in a role. This is a double round trip: once to list
+ * the nodes in a role, another to get their details
+ * @param role
+ * @return an array of ContainerNode instances
+ * @throws IOException
+ * @throws YarnException
+ */
+ public List<ClusterNode> listClusterNodesInRole(String role)
+ throws IOException, YarnException {
+
+ Collection<String> uuidList = innerListNodeUUIDSByRole(role);
+ Messages.GetClusterNodesRequestProto req =
+ Messages.GetClusterNodesRequestProto
+ .newBuilder()
+ .addAllUuid(uuidList)
+ .build();
+ Messages.GetClusterNodesResponseProto resp = appMaster.getClusterNodes(req);
+ return convertNodeWireToClusterNodes(resp.getClusterNodeList());
+ }
+
+ /**
+ * Get the details on a list of uuids
+ * @param uuids instance IDs
+ * @return a possibly empty list of node details
+ * @throws IOException
+ * @throws YarnException
+ */
+ @VisibleForTesting
+ public List<ClusterNode> listClusterNodes(String[] uuids)
+ throws IOException, YarnException {
+
+ Messages.GetClusterNodesRequestProto req =
+ Messages.GetClusterNodesRequestProto
+ .newBuilder()
+ .addAllUuid(Arrays.asList(uuids))
+ .build();
+ Messages.GetClusterNodesResponseProto resp = appMaster.getClusterNodes(req);
+ return convertNodeWireToClusterNodes(resp.getClusterNodeList());
+ }
+
+ /**
+ * Wait for an instance of a named role to be live (or past it in the lifecycle)
+ * @param role role to look for
+ * @param timeout time to wait
+ * @return the state. If still in CREATED, the cluster didn't come up
+ * in the time period. If LIVE, all is well. If >LIVE, it has shut for a reason
+ * @throws IOException IO
+ * @throws SliderException Slider
+ * @throws WaitTimeoutException if the wait timed out
+ */
+ @VisibleForTesting
+ public int waitForRoleInstanceLive(String role, long timeout)
+ throws WaitTimeoutException, IOException, YarnException {
+ Duration duration = new Duration(timeout);
+ duration.start();
+ boolean live = false;
+ int state = StateValues.STATE_CREATED;
+
+ log.info("Waiting {} millis for a live node in role {}", timeout, role);
+ try {
+ while (!live) {
+ // see if there is a node in that role yet
+ List<String> uuids = innerListNodeUUIDSByRole(role);
+ String[] containers = uuids.toArray(new String[uuids.size()]);
+ int roleCount = containers.length;
+ ClusterNode roleInstance = null;
+ if (roleCount != 0) {
+
+ // if there is, get the node
+ roleInstance = getNode(containers[0]);
+ if (roleInstance != null) {
+ state = roleInstance.state;
+ live = state >= StateValues.STATE_LIVE;
+ }
+ }
+ if (!live) {
+ if (duration.getLimitExceeded()) {
+ throw new WaitTimeoutException(
+ String.format("Timeout after %d millis" +
+ " waiting for a live instance of type %s; " +
+ "instances found %d %s",
+ timeout, role, roleCount,
+ (roleInstance != null
+ ? (" instance -\n" + roleInstance.toString())
+ : "")
+ ));
+ } else {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ignored) {
+ // ignored
+ }
+ }
+ }
+ }
+ } finally {
+ duration.close();
+ }
+ return state;
+ }
+
+ /**
+ * Flex operation
+ * @param resources new resources
+ * @return the response
+ * @throws IOException
+ */
+ public boolean flex(ConfTree resources) throws IOException {
+ Messages.FlexClusterRequestProto request =
+ Messages.FlexClusterRequestProto.newBuilder()
+ .setClusterSpec(resources.toJson())
+ .build();
+ Messages.FlexClusterResponseProto response = appMaster.flexCluster(request);
+ return response.getResponse();
+ }
+
+
+ /**
+ * Commit (possibly delayed) AM suicide
+ *
+ * @param signal exit code
+ * @param text text text to log
+ * @param delay delay in millis
+ * @throws YarnException
+ * @throws IOException
+ */
+ public void amSuicide(String text, int signal, int delay)
+ throws IOException {
+ Messages.AMSuicideRequestProto.Builder builder =
+ Messages.AMSuicideRequestProto.newBuilder();
+ if (text != null) {
+ builder.setText(text);
+ }
+ builder.setSignal(signal);
+ builder.setDelay(delay);
+ Messages.AMSuicideRequestProto req = builder.build();
+ appMaster.amSuicide(req);
+ }
+
+ /**
+ * Get the application liveness
+ * @return current liveness information
+ * @throws IOException
+ */
+ public ApplicationLivenessInformation getLivenessInformation() throws IOException {
+ Messages.GetApplicationLivenessRequestProto.Builder builder =
+ Messages.GetApplicationLivenessRequestProto.newBuilder();
+ Messages.ApplicationLivenessInformationProto wire =
+ appMaster.getLivenessInformation(builder.build());
+ return unmarshall(wire);
+
+ }
+
+ public AggregateConf getModelDesired() throws IOException {
+ return unmarshallToAggregateConf(appMaster.getModelDesired(EMPTY));
+ }
+
+
+ public ConfTreeOperations getModelDesiredAppconf() throws IOException {
+ return unmarshallToCTO(appMaster.getModelDesiredAppconf(EMPTY));
+ }
+
+
+ public ConfTreeOperations getModelDesiredResources() throws IOException {
+ return unmarshallToCTO(appMaster.getModelDesiredResources(EMPTY));
+ }
+
+
+ public AggregateConf getModelResolved() throws IOException {
+ return unmarshallToAggregateConf(appMaster.getModelResolved(EMPTY));
+ }
+
+
+ public ConfTreeOperations getModelResolvedAppconf() throws IOException {
+ return unmarshallToCTO(appMaster.getModelResolvedAppconf(EMPTY));
+ }
+
+
+ public ConfTreeOperations getModelResolvedResources() throws IOException {
+ return unmarshallToCTO(appMaster.getModelDesiredResources(EMPTY));
+ }
+
+
+ public ConfTreeOperations getLiveResources() throws IOException {
+ return unmarshallToCTO(appMaster.getLiveResources(EMPTY));
+ }
+
+
+ public Map<String, ContainerInformation> enumContainers() throws IOException {
+ Messages.GetLiveContainersResponseProto response =
+ appMaster.getLiveContainers(
+ Messages.GetLiveContainersRequestProto.newBuilder().build());
+
+ int namesCount = response.getNamesCount();
+ int records = response.getContainersCount();
+ if (namesCount != records) {
+ throw new IOException("Number of names returned (" + namesCount
+ + ") does not match the number of records returned: "
+ + records);
+ }
+ Map<String, ContainerInformation> map = new HashMap<>(namesCount);
+ for (int i = 0; i < namesCount; i++) {
+ map.put(response.getNames(i), unmarshall(response.getContainers(i)));
+ }
+ return map;
+ }
+
+
+ public ContainerInformation getContainer(String containerId) throws
+ IOException {
+ Messages.ContainerInformationProto response =
+ appMaster.getLiveContainer(
+ Messages.GetLiveContainerRequestProto.newBuilder()
+ .setContainerId(containerId)
+ .build());
+ return unmarshall(response);
+ }
+
+ public List<ContainerInformation> getContainers() throws IOException {
+ Messages.GetLiveContainersResponseProto response = appMaster
+ .getLiveContainers(Messages.GetLiveContainersRequestProto.newBuilder()
+ .build());
+ return unmarshall(response);
+ }
+
+ public Map<String, ComponentInformation> enumComponents() throws IOException {
+ Messages.GetLiveComponentsResponseProto response =
+ appMaster.getLiveComponents(
+ Messages.GetLiveComponentsRequestProto.newBuilder().build());
+
+ int namesCount = response.getNamesCount();
+ int records = response.getComponentsCount();
+ if (namesCount != records) {
+ throw new IOException(
+ "Number of names returned (" + namesCount + ")" +
+ " does not match the number of records returned: " + records);
+ }
+ Map<String, ComponentInformation> map = new HashMap<>(namesCount);
+ for (int i = 0; i < namesCount; i++) {
+ map.put(response.getNames(i), unmarshall(response.getComponents(i)));
+ }
+ return map;
+ }
+
+ public ComponentInformation getComponent(String componentName)
+ throws IOException {
+ Messages.GetLiveComponentRequestProto.Builder builder =
+ Messages.GetLiveComponentRequestProto.newBuilder();
+ builder.setName(componentName);
+ Messages.ComponentInformationProto proto = appMaster.getLiveComponent(builder.build());
+ return unmarshall(proto);
+ }
+
+ public NodeInformationList getLiveNodes() throws IOException {
+ Messages.GetLiveNodesResponseProto response =
+ appMaster.getLiveNodes(Messages.GetLiveNodesRequestProto.newBuilder().build());
+
+ int records = response.getNodesCount();
+ NodeInformationList nil = new NodeInformationList(records);
+ for (int i = 0; i < records; i++) {
+ nil.add(unmarshall(response.getNodes(i)));
+ }
+ return nil;
+ }
+
+ public NodeInformation getLiveNode(String hostname) throws IOException {
+ Messages.GetLiveNodeRequestProto.Builder builder =
+ Messages.GetLiveNodeRequestProto.newBuilder();
+ builder.setName(hostname);
+ return unmarshall(appMaster.getLiveNode(builder.build()));
+ }
+
+ public PingInformation ping(String text) throws IOException {
+ return null;
+ }
+
+ public void stop(String text) throws IOException {
+ amSuicide(text, 3, 0);
+ }
+
+ public ApplicationLivenessInformation getApplicationLiveness() throws
+ IOException {
+ Messages.ApplicationLivenessInformationProto proto =
+ appMaster.getLivenessInformation(
+ Messages.GetApplicationLivenessRequestProto.newBuilder().build()
+ );
+ return unmarshall(proto);
+ }
+
+ public byte[] getClientCertificateStore(String hostname, String clientId,
+ String password, String type) throws IOException {
+ Messages.GetCertificateStoreRequestProto.Builder
+ builder = Messages.GetCertificateStoreRequestProto.newBuilder();
+ if (hostname != null) {
+ builder.setHostname(hostname);
+ }
+ Messages.GetCertificateStoreRequestProto requestProto =
+ builder.setRequesterId(clientId)
+ .setPassword(password)
+ .setType(type)
+ .build();
+ Messages.GetCertificateStoreResponseProto response =
+ appMaster.getClientCertificateStore(requestProto);
+
+ return unmarshall(response);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/BaseRestClient.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/BaseRestClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/BaseRestClient.java
new file mode 100644
index 0000000..d936a22
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/BaseRestClient.java
@@ -0,0 +1,152 @@
+/*
+ * 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.client.rest;
+
+import com.google.common.base.Preconditions;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.GenericType;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+import org.apache.slider.core.exceptions.ExceptionConverter;
+import org.apache.slider.core.restclient.HttpVerb;
+import org.apache.slider.core.restclient.UgiJerseyBinding;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+import java.net.URI;
+
+
+/**
+ * This is a base class for Jersey REST clients in Slider.
+ * It supports the execution of operations \u2014with
+ * exceptions uprated to IOExceptions when needed.
+ * <p>
+ * Subclasses can use these operations to provide an API-like view
+ * of the REST model
+ */
+public class BaseRestClient {
+ private static final Logger log =
+ LoggerFactory.getLogger(BaseRestClient.class);
+ private final Client client;
+
+ public BaseRestClient(
+ Client client) {
+ Preconditions.checkNotNull(client, "null jersey client");
+ this.client = client;
+ }
+
+ /**
+ * Get the jersey client
+ * @return jersey client
+ */
+ public Client getClient() {
+ return client;
+ }
+
+ /**
+ * Execute the operation. Failures are raised as IOException subclasses
+ * @param method method to execute
+ * @param resource resource to work against
+ * @param c class to build
+ * @param <T> type expected
+ * @return an instance of the type T
+ * @throws IOException on any failure
+ */
+ public <T> T exec(HttpVerb method, WebResource resource, Class<T> c)
+ throws IOException {
+ try {
+ Preconditions.checkArgument(c != null);
+ log.debug("{}} {}", method, resource.getURI());
+ return resource.accept(MediaType.APPLICATION_JSON_TYPE)
+ .method(method.getVerb(), c);
+ } catch (ClientHandlerException ex) {
+ throw ExceptionConverter.convertJerseyException(method.getVerb(),
+ resource.getURI().toString(),
+ ex);
+ } catch (UniformInterfaceException ex) {
+ throw UgiJerseyBinding.uprateFaults(method,
+ resource.getURI().toString(),
+ ex);
+ }
+ }
+
+ /**
+ * Execute the operation. Failures are raised as IOException subclasses
+ * @param method method to execute
+ * @param resource resource to work against
+ * @param t type to work with
+ * @param <T> type expected
+ * @return an instance of the type T
+ * @throws IOException on any failure
+ */
+ public <T> T exec(HttpVerb method, WebResource resource, GenericType<T> t)
+ throws IOException {
+ try {
+ Preconditions.checkArgument(t != null);
+ log.debug("{}} {}", method, resource.getURI());
+ resource.accept(MediaType.APPLICATION_JSON_TYPE);
+ return resource.method(method.getVerb(), t);
+ } catch (ClientHandlerException ex) {
+ throw ExceptionConverter.convertJerseyException(method.getVerb(),
+ resource.getURI().toString(),
+ ex);
+ } catch (UniformInterfaceException ex) {
+ throw UgiJerseyBinding.uprateFaults(method, resource.getURI().toString(),
+ ex);
+ }
+ }
+
+
+ /**
+ * Execute the GET operation. Failures are raised as IOException subclasses
+ * @param resource resource to work against
+ * @param c class to build
+ * @param <T> type expected
+ * @return an instance of the type T
+ * @throws IOException on any failure
+ */
+ public <T> T get(WebResource resource, Class<T> c) throws IOException {
+ return exec(HttpVerb.GET, resource, c);
+ }
+
+ /**
+ * Create a Web resource from the client.
+ *
+ * @param u the URI of the resource.
+ * @return the Web resource.
+ */
+ public WebResource resource(URI u) {
+ return client.resource(u);
+ }
+
+ /**
+ * Create a Web resource from the client.
+ *
+ * @param u the URI of the resource.
+ * @return the Web resource.
+ */
+
+ public WebResource resource(String url) {
+ return client.resource(url);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/RestClientFactory.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/RestClientFactory.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/RestClientFactory.java
new file mode 100644
index 0000000..4286596
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/RestClientFactory.java
@@ -0,0 +1,89 @@
+/*
+ * 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.client.rest;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.WebResource;
+import org.apache.hadoop.registry.client.api.RegistryOperations;
+import org.apache.slider.client.ClientRegistryBinder;
+import org.apache.slider.api.SliderApplicationApi;
+import org.apache.slider.core.registry.info.CustomRegistryConstants;
+
+import java.io.IOException;
+
+import static org.apache.slider.server.appmaster.web.rest.RestPaths.SLIDER_PATH_APPLICATION;
+
+/**
+ * Factory for the Rest client; hides the lookup and instantiation.
+ * <p>
+ *
+ */
+public class RestClientFactory {
+
+ private final ClientRegistryBinder binder;
+ private final Client jerseyClient;
+ private final String user, serviceclass, instance;
+
+ public RestClientFactory(RegistryOperations operations,
+ Client jerseyClient,
+ String user,
+ String serviceclass,
+ String instance) {
+ this.jerseyClient = jerseyClient;
+ this.user = user;
+ this.serviceclass = serviceclass;
+ this.instance = instance;
+ binder = new ClientRegistryBinder(operations);
+ }
+
+ /**
+ * Locate the AM
+ * @return a resource to the AM
+ * @throws IOException any failure to resolve to the AM
+ */
+ private WebResource locateAppmaster() throws IOException {
+ String restAPI = binder.lookupExternalRestAPI(user, serviceclass, instance,
+ CustomRegistryConstants.AM_REST_BASE);
+ return jerseyClient.resource(restAPI);
+ }
+
+ /**
+ * Locate the slider AM then instantiate a client instance against
+ * its Application API.
+ * @return the instance
+ * @throws IOException on any failure
+ */
+ public SliderApplicationApi createSliderAppApiClient() throws IOException {
+ WebResource appmaster = locateAppmaster();
+ return createSliderAppApiClient(appmaster);
+ }
+
+ /**
+ * Create a Slider application API client instance against
+ * its Application API.
+ * @param appmaster The AM to work against.
+ * @return the instance
+ * @throws IOException on any failure
+ */
+ public SliderApplicationApi createSliderAppApiClient(WebResource appmaster) {
+ WebResource appResource = appmaster.path(SLIDER_PATH_APPLICATION);
+ return new SliderApplicationApiRestClient(jerseyClient, appResource);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/SliderApplicationApiRestClient.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/SliderApplicationApiRestClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/SliderApplicationApiRestClient.java
new file mode 100644
index 0000000..4283ee8
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/client/rest/SliderApplicationApiRestClient.java
@@ -0,0 +1,326 @@
+/*
+ * 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.client.rest;
+
+import com.google.common.base.Preconditions;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.GenericType;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.representation.Form;
+import org.apache.commons.lang.StringUtils;
+import org.apache.slider.api.types.ApplicationLivenessInformation;
+import org.apache.slider.api.types.ComponentInformation;
+import org.apache.slider.api.types.ContainerInformation;
+import org.apache.slider.api.SliderApplicationApi;
+import org.apache.slider.api.types.NodeInformation;
+import org.apache.slider.api.types.NodeInformationList;
+import org.apache.slider.core.conf.AggregateConf;
+import org.apache.slider.core.conf.ConfTree;
+import org.apache.slider.core.conf.ConfTreeOperations;
+import org.apache.slider.core.exceptions.ExceptionConverter;
+import org.apache.slider.core.restclient.HttpVerb;
+import org.apache.slider.api.types.PingInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+import java.util.Map;
+
+import static org.apache.slider.server.appmaster.web.rest.RestPaths.*;
+
+/**
+ * Implementation of the {@link SliderApplicationApi}
+ */
+public class SliderApplicationApiRestClient extends BaseRestClient
+ implements SliderApplicationApi {
+ private static final Logger log =
+ LoggerFactory.getLogger(SliderApplicationApiRestClient.class);
+ private WebResource appResource;
+
+ /**
+ * Create an instance
+ * @param jerseyClient jersey client for operations
+ * @param appResource resource of application API
+ */
+ public SliderApplicationApiRestClient(Client jerseyClient,
+ WebResource appResource) {
+ super(jerseyClient);
+ this.appResource = appResource;
+ }
+
+ /**
+ * Create an instance
+ * @param jerseyClient jersey client for operations
+ * @param appmaster URL of appmaster/proxy to AM
+ */
+ public SliderApplicationApiRestClient(Client jerseyClient, String appmaster) {
+ super(jerseyClient);
+ WebResource amResource = jerseyClient.resource(appmaster);
+ amResource.type(MediaType.APPLICATION_JSON);
+ this.appResource = amResource.path(SLIDER_PATH_APPLICATION);
+ }
+
+
+ @Override
+ public String toString() {
+ final StringBuilder sb =
+ new StringBuilder("SliderApplicationApiRestClient{");
+ sb.append("appResource=").append(appResource);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ /**
+ * Create a resource under the application path
+ * @param subpath path under application
+ * @return a resource under the application path
+ */
+ public WebResource applicationResource(String subpath) {
+ Preconditions.checkArgument(!StringUtils.isEmpty(subpath),
+ "empty path");
+ Preconditions.checkNotNull(appResource, "Null app resource");
+ return appResource.path(subpath);
+ }
+
+ /**
+ * Get operation against a path under the Application
+ * @param <T> type expected
+ * @param subpath path
+ * @param c class to instantiate
+ * @return instance
+ * @throws IOException on any problem
+ */
+ public <T> T getApplicationResource(String subpath, Class<T> c)
+ throws IOException {
+ return appResourceOperation(HttpVerb.GET, subpath, c);
+ }
+
+ /**
+ * Get operation against a path under the Application
+ * @param <T> type expected
+ * @param subpath path
+ * @param t type info
+ * @return instance
+ * @throws IOException on any problem
+ */
+ public <T> T getApplicationResource(String subpath, GenericType<T> t)
+ throws IOException {
+ return appResourceOperation(HttpVerb.GET, subpath, t);
+ }
+
+ /**
+ *
+ * @param method method to exec
+ * @param <T> type expected
+ * @param subpath path
+ * @param c class to instantiate
+ * @return instance
+ * @throws IOException on any problem
+ */
+ public <T> T appResourceOperation(HttpVerb method, String subpath, Class<T> c)
+ throws IOException {
+ return exec(method, applicationResource(subpath), c);
+ }
+
+
+ /**
+ * Get operation against a path under the Application
+ * @param <T> type expected
+ * @param subpath path
+ * @param t type info
+ * @return instance
+ * @throws IOException on any problem
+ */
+ public <T> T appResourceOperation(HttpVerb method, String subpath,
+ GenericType<T> t)
+ throws IOException {
+ return exec(method, applicationResource(subpath), t);
+ }
+
+
+ @Override
+ public AggregateConf getDesiredModel() throws IOException {
+ return getApplicationResource(MODEL_DESIRED, AggregateConf.class);
+ }
+
+ @Override
+ public ConfTreeOperations getDesiredAppconf() throws IOException {
+ ConfTree resource =
+ getApplicationResource(MODEL_DESIRED_APPCONF, ConfTree.class);
+ return new ConfTreeOperations(resource);
+ }
+
+ @Override
+ public ConfTreeOperations getDesiredResources() throws IOException {
+ ConfTree resource =
+ getApplicationResource(MODEL_DESIRED_RESOURCES, ConfTree.class);
+ return new ConfTreeOperations(resource);
+ }
+
+ @Override
+ public void putDesiredResources(ConfTree updated) throws IOException {
+ WebResource resource = applicationResource(MODEL_DESIRED_RESOURCES);
+ try {
+
+ // put operation. The result is discarded; it does help validate
+ // that the operation returned a JSON data structure as well as a 200
+ // response.
+
+ resource.accept(MediaType.APPLICATION_JSON_TYPE)
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .entity(updated)
+ .put(ConfTree.class);
+ } catch (ClientHandlerException ex) {
+ throw ExceptionConverter.convertJerseyException("PUT",
+ resource.getURI().toString(),
+ ex);
+ } catch (UniformInterfaceException ex) {
+ throw ExceptionConverter.convertJerseyException("PUT",
+ resource.getURI().toString(), ex);
+ }
+ }
+
+ @Override
+ public AggregateConf getResolvedModel() throws IOException {
+ return getApplicationResource(MODEL_RESOLVED, AggregateConf.class);
+ }
+
+
+ @Override
+ public ConfTreeOperations getResolvedAppconf() throws IOException {
+ ConfTree resource =
+ getApplicationResource(MODEL_RESOLVED_APPCONF, ConfTree.class);
+ return new ConfTreeOperations(resource);
+ }
+
+ @Override
+ public ConfTreeOperations getResolvedResources() throws IOException {
+ ConfTree resource =
+ getApplicationResource(MODEL_RESOLVED_RESOURCES, ConfTree.class);
+ return new ConfTreeOperations(resource);
+ }
+
+ @Override
+ public ConfTreeOperations getLiveResources() throws IOException {
+ ConfTree resource =
+ getApplicationResource(LIVE_RESOURCES, ConfTree.class);
+ return new ConfTreeOperations(resource);
+ }
+
+ @Override
+ public Map<String, ContainerInformation> enumContainers() throws
+ IOException {
+ return getApplicationResource(LIVE_CONTAINERS,
+ new GenericType<Map<String, ContainerInformation>>() {
+ });
+ }
+
+ @Override
+ public ContainerInformation getContainer(String containerId) throws
+ IOException {
+ return getApplicationResource(LIVE_CONTAINERS + "/" + containerId,
+ ContainerInformation.class);
+ }
+
+ @Override
+ public Map<String, ComponentInformation> enumComponents() throws
+ IOException {
+ return getApplicationResource(LIVE_COMPONENTS,
+ new GenericType<Map<String, ComponentInformation>>() { });
+ }
+
+ @Override
+ public ComponentInformation getComponent(String componentName) throws
+ IOException {
+ return getApplicationResource(LIVE_COMPONENTS + "/" + componentName,
+ ComponentInformation.class);
+ }
+
+ @Override
+ public NodeInformationList getLiveNodes() throws IOException {
+ return getApplicationResource(LIVE_NODES, NodeInformationList.class);
+ }
+
+ @Override
+ public NodeInformation getLiveNode(String hostname) throws IOException {
+ return getApplicationResource(LIVE_NODES + "/" + hostname,
+ NodeInformation.class);
+ }
+
+ @Override
+ public PingInformation ping(String text) throws IOException {
+ return pingPost(text);
+ }
+
+ /**
+ * Ping as a GET
+ * @param text text to include
+ * @return the response
+ * @throws IOException on any failure
+ */
+ public PingInformation pingGet(String text) throws IOException {
+ WebResource pingResource = applicationResource(ACTION_PING);
+ pingResource.getUriBuilder().queryParam("body", text);
+ return pingResource.get(PingInformation.class);
+ }
+
+ /**
+ * Ping as a POST
+ * @param text text to include
+ * @return the response
+ * @throws IOException on any failure
+ */
+ public PingInformation pingPost(String text) throws IOException {
+ WebResource pingResource = applicationResource(ACTION_PING);
+ Form f = new Form();
+ f.add("text", text);
+ return pingResource
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .post(PingInformation.class, f);
+ }
+
+ /**
+ * Ping as a POST
+ * @param text text to include
+ * @return the response
+ * @throws IOException on any failure
+ */
+ public PingInformation pingPut(String text) throws IOException {
+ WebResource pingResource = applicationResource(ACTION_PING);
+ Form f = new Form();
+ return pingResource
+ .type(MediaType.TEXT_PLAIN)
+ .put(PingInformation.class, text);
+ }
+
+ @Override
+ public void stop(String text) throws IOException {
+ WebResource resource = applicationResource(ACTION_STOP);
+ resource.post(text);
+ }
+
+ @Override
+ public ApplicationLivenessInformation getApplicationLiveness() throws IOException {
+ return getApplicationResource(LIVE_LIVENESS,
+ ApplicationLivenessInformation.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/hadoop/blob/d8cab88d/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/common/Constants.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/common/Constants.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/common/Constants.java
new file mode 100644
index 0000000..0e3559a
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-applications/hadoop-yarn-slider/hadoop-yarn-slider-core/src/main/java/org/apache/slider/common/Constants.java
@@ -0,0 +1,35 @@
+/*
+ * 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.common;
+
+public class Constants {
+ public static final int CONNECT_TIMEOUT = 10000;
+ public static final int RPC_TIMEOUT = 15000;
+
+ public static final String HADOOP_JAAS_DEBUG = "HADOOP_JAAS_DEBUG";
+ public static final String KRB5_CCNAME = "KRB5CCNAME";
+ public static final String JAVA_SECURITY_KRB5_CONF
+ = "java.security.krb5.conf";
+ public static final String JAVA_SECURITY_KRB5_REALM
+ = "java.security.krb5.realm";
+ public static final String SUN_SECURITY_KRB5_DEBUG
+ = "sun.security.krb5.debug";
+ public static final String SUN_SECURITY_SPNEGO_DEBUG
+ = "sun.security.spnego.debug";
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org