├── .arcconfig
├── .gitignore
├── README.md
├── distributed-docker-appmaster
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── sogou
│ │ └── dockeronyarn
│ │ ├── appmaster
│ │ └── DockerRunnerApplicationMaster.java
│ │ ├── common
│ │ ├── DSConstants.java
│ │ ├── DistributedDockerConfiguration.java
│ │ ├── ExitCode.java
│ │ ├── Log4jPropertyHelper.java
│ │ └── Utils.java
│ │ └── docker
│ │ ├── Constants.java
│ │ ├── DockerContainerRunner.java
│ │ ├── DockerContainerRunnerParam.java
│ │ ├── DockerShareSpaceMonitor.java
│ │ ├── ExitCode.java
│ │ └── Test.java
│ └── resources
│ └── META-INF
│ └── services
│ └── javax.ws.rs.ext.RuntimeDelegate
├── distributed-docker-submit-client
├── .classpath
├── .project
├── .settings
│ ├── org.eclipse.core.resources.prefs
│ ├── org.eclipse.jdt.core.prefs
│ └── org.eclipse.m2e.core.prefs
├── DockerApplicationMaster_24.java
├── README.MD
├── hadoop-env.sh
├── log4j.properties
├── pom.xml
├── run_YarnDockerClient.sh
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── sogou
│ │ │ └── dockeronyarn
│ │ │ └── client
│ │ │ ├── DockerApplicationMaster_23.java
│ │ │ ├── DockerApplicationSubmitter.java
│ │ │ ├── DockerClient.java
│ │ │ ├── DockerOnYarnAppDescriptor.java
│ │ │ ├── DockerOnYarnClient.java
│ │ │ ├── DockerOnYarnClientCli.java
│ │ │ └── model
│ │ │ ├── SubmitException.java
│ │ │ ├── SubmitItem.java
│ │ │ └── SubmitReturnItem.java
│ │ └── resources
│ │ ├── META-INF
│ │ └── services
│ │ │ └── javax.ws.rs.ext.RuntimeDelegate
│ │ ├── distributed-docker-site.xml
│ │ └── log4j.properties
└── test_docker_client.sh
├── distributed-docker-submit-server
├── .classpath
├── .project
├── .settings
│ ├── org.eclipse.core.resources.prefs
│ ├── org.eclipse.jdt.core.prefs
│ └── org.eclipse.m2e.core.prefs
├── assembly.xml
├── bin
│ ├── monitor_docker_submit_server.sh
│ ├── start_server.sh
│ └── test.sh
├── conf
│ ├── log.properties
│ └── server.properties
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── sogou
│ └── dockeronyarn
│ ├── server
│ ├── DockerServer.java
│ └── DockerSubmitMain.java
│ ├── service
│ └── DockerService.java
│ └── util
│ ├── LogUtil.java
│ ├── PropertyManager.java
│ └── StaticData.java
└── pom.xml
/.arcconfig:
--------------------------------------------------------------------------------
1 | {
2 | "phabricator.uri" : "http://review.dev.sogou-inc.com/"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | target/
3 | *.iml
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Docker on yarn - Unified Resource Management Submit System
2 |
3 | ---
4 |
5 | Docker ont yarn is a simply system to submit your hadoop job.
6 |
7 | ---
8 |
9 | ## User Guide
10 |
11 | ### Maven Dependency
12 |
13 | ```
14 |
15 | distributed-docker-submit-project
16 | distributed-docker-submit-project
17 | 0.0.1-SNAPSHOT
18 |
19 | ```
20 |
21 | ---
22 |
23 | ## Developer Guide
24 |
25 | ### Requirements
26 |
27 | * JDK-1.7
28 | * Maven 3.0.3 above
29 |
30 | ### Building
31 |
32 | ```
33 | $ mvn clean package
34 | ```
35 |
36 | * jar location: distributed-docker-appmaster/target/,distributed-docker-submit-client-0.0.1-SNAPSHOT.jar
37 |
38 | ### Deploy To Remote Maven Repository
39 |
40 | ```
41 | $ mvn deploy
42 | ```
43 |
44 | ---
45 |
--------------------------------------------------------------------------------
/distributed-docker-appmaster/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | distributed-docker-submit-project
7 | distributed-docker-submit-project
8 | 0.0.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | distributed-docker-appmaster
13 |
14 |
15 |
16 | true
17 |
18 | UTF-8
19 | true
20 | false
21 | 1.7
22 | 1.7
23 |
24 |
25 |
26 |
27 |
28 | org.apache.hadoop
29 | hadoop-common
30 | 2.5.0-cdh5.3.2
31 |
32 |
33 |
34 | jersey-core
35 | com.sun.jersey
36 |
37 |
38 | com.sun.jersey
39 | jersey-server
40 |
41 |
42 |
43 |
44 |
45 |
46 | org.apache.hadoop
47 | hadoop-yarn-client
48 | 2.5.0-cdh5.3.2
49 |
50 |
51 |
52 | jersey-core
53 | com.sun.jersey
54 |
55 |
56 | com.sun.jersey
57 | jersey-server
58 |
59 |
60 |
61 |
62 |
63 | com.github.docker-java
64 | docker-java
65 | 2.2.3
66 |
67 |
68 |
69 | org.apache.httpcomponents
70 | httpcore
71 | 4.3.1
72 |
73 |
74 |
75 |
76 |
77 |
78 | maven-compiler-plugin
79 | 3.0
80 |
81 | 1.6
82 | 1.6
83 | GB18030
84 |
85 |
86 |
87 |
88 | org.apache.maven.plugins
89 | maven-jar-plugin
90 | 2.4
91 |
92 |
93 |
94 | true
95 |
96 |
97 |
98 |
99 |
100 |
101 | org.apache.maven.plugins
102 | maven-assembly-plugin
103 | 2.5.4
104 |
105 |
106 | jar-with-dependencies
107 |
108 |
109 |
110 |
111 |
112 | assemble-all
113 | package
114 |
115 | single
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/distributed-docker-appmaster/src/main/java/com/sogou/dockeronyarn/appmaster/DockerRunnerApplicationMaster.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.appmaster;
2 |
3 | import com.sogou.dockeronyarn.docker.DockerContainerRunner;
4 | import com.sogou.dockeronyarn.common.Log4jPropertyHelper;
5 | import com.sogou.dockeronyarn.common.Utils;
6 | import com.sogou.dockeronyarn.docker.DockerContainerRunnerParam;
7 | import com.sogou.dockeronyarn.common.DistributedDockerConfiguration;
8 | import org.apache.commons.cli.*;
9 | import org.apache.commons.logging.Log;
10 | import org.apache.commons.logging.LogFactory;
11 | import org.apache.hadoop.conf.Configuration;
12 | import org.apache.hadoop.io.DataOutputBuffer;
13 | import org.apache.hadoop.io.IOUtils;
14 | import org.apache.hadoop.net.NetUtils;
15 | import org.apache.hadoop.security.Credentials;
16 | import org.apache.hadoop.security.UserGroupInformation;
17 | import org.apache.hadoop.security.token.Token;
18 | import org.apache.hadoop.util.Shell;
19 | import org.apache.hadoop.yarn.api.ApplicationConstants;
20 | import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse;
21 | import org.apache.hadoop.yarn.api.records.*;
22 | import org.apache.hadoop.yarn.client.api.async.AMRMClientAsync;
23 | import org.apache.hadoop.yarn.conf.YarnConfiguration;
24 | import org.apache.hadoop.yarn.exceptions.YarnException;
25 | import org.apache.hadoop.yarn.security.AMRMTokenIdentifier;
26 | import org.apache.hadoop.yarn.util.ConverterUtils;
27 |
28 | import java.io.BufferedReader;
29 | import java.io.File;
30 | import java.io.IOException;
31 | import java.io.StringReader;
32 | import java.util.Iterator;
33 | import java.util.List;
34 | import java.util.Map;
35 | import java.util.concurrent.atomic.AtomicInteger;
36 |
37 | import static com.sogou.dockeronyarn.common.Utils.checkNotEmpty;
38 |
39 | /**
40 | * The DockerRunnerApplicationMaster DONOT require more container from RM.
41 | * It only create and run a new container to docker service on the local host
42 | * where the AM is launched.
43 | *
44 | * Created by guoshiwei on 15/4/25.
45 | */
46 | public class DockerRunnerApplicationMaster {
47 | public static final String LOCAL_RUNNER_NAME = "runner.py";
48 | private static final Log LOG = LogFactory.getLog(DockerRunnerApplicationMaster.class);
49 | private Configuration conf;
50 | // Handle to communicate with the Resource Manager
51 | @SuppressWarnings("rawtypes")
52 | private AMRMClientAsync amRMClient;
53 | private ApplicationAttemptId appAttemptID;
54 | // Hostname of the container
55 | private String appMasterHostname = "localhost";
56 | // Port on which the app master listens for status updates from clients
57 | private int appMasterRpcPort = 9999;
58 | // Tracking url to which app master publishes info for clients to monitor
59 | private String appMasterTrackingUrl = ""; //"http://localhost:9999/someurl";
60 | private String appHistoryTrackingUrlBase = "";
61 | // Hardcoded path to custom log_properties
62 | private static final String log4jPath = "log4j.properties";
63 | protected AtomicInteger numRetryCount = new AtomicInteger();
64 | protected AtomicInteger MAX_RETRY_COUNT = new AtomicInteger(3);
65 | private String mountVolume ="";
66 | private String workDir="";
67 | private DockerContainerRunner dockerContainerRunner;
68 | private volatile boolean done;
69 | private String workingDirectory ;
70 | private String dockerImage;
71 | private String[] commandToRun;
72 | private String jobName;
73 | private String[] dockerArgs ;
74 |
75 | public String getRunnerAbsolutePath() {
76 | return workingDirectory + "/" + LOCAL_RUNNER_NAME;
77 | }
78 |
79 | private DockerContainerRunnerParam buildYarnDockerClientParam() {
80 | DockerContainerRunnerParam p = new DockerContainerRunnerParam();
81 | DistributedDockerConfiguration dockerConf = new DistributedDockerConfiguration();
82 | p.cmdAndArgs = commandToRun;
83 | p.containerMemory = dockerConf.getInt(DistributedDockerConfiguration.CONTAINER_MEMORY,
84 | DistributedDockerConfiguration.DEFAULT_CONTAINER_MEMORY);
85 | p.containerVirtualCores = dockerConf.getInt(DistributedDockerConfiguration.CONTAINER_CORES,
86 | DistributedDockerConfiguration.DEFAULT_CONTAINER_CORES);
87 |
88 | p.runnerScriptPath = getRunnerAbsolutePath();
89 | p.dockerCertPath = dockerConf.get(DistributedDockerConfiguration.DOCKER_CERT_PATH);
90 | Utils.checkNotEmpty(p.dockerCertPath, DistributedDockerConfiguration.DOCKER_CERT_PATH + " Not given");
91 | p.dockerHost = dockerConf.get(DistributedDockerConfiguration.DOCKER_HOST,
92 | DistributedDockerConfiguration.DEFAULT_DOCKER_HOST);
93 |
94 | p.dockerImage = this.dockerImage;
95 | p.mountVolume = this.mountVolume ;
96 | p.workingDir = this.workDir;
97 | p.setDockerArgs(dockerArgs);
98 | return p;
99 | }
100 | //init the docker options
101 | public static Options InitDockerOptions() {
102 | Options opts = new Options();
103 | opts.addOption("v", true, "the mount volume");
104 | opts.addOption(OptionBuilder.withLongOpt("rm")
105 | .withDescription("rm the container after execute").create());
106 | opts.addOption(new Option("m","memory",true,"the memory of container"));
107 | opts.addOption(new Option("c","cpu-shares",true,"the cpu of the container"));
108 | opts.addOption(new Option("H","cpu-shares",true,"the host of the container"));
109 | return opts;
110 | }
111 |
112 | public DockerRunnerApplicationMaster() {
113 | // Set up the configuration
114 | conf = new YarnConfiguration();
115 | appHistoryTrackingUrlBase = conf.get("yarn.timeline-service.webapp.address");
116 | if (appHistoryTrackingUrlBase == null || appHistoryTrackingUrlBase.isEmpty()) {
117 | throw new IllegalArgumentException("No yarn.timeline-service.webapp.address is found." +
118 | "Check your yarn-site.xml");
119 | }
120 |
121 | appHistoryTrackingUrlBase = "http://" + appHistoryTrackingUrlBase + "/applicationhistory/app/";
122 | workingDirectory = System.getenv("PWD");
123 | checkNotEmpty(workingDirectory, "PWD enviroment is not set");
124 | if (!new File(getRunnerAbsolutePath()).isFile()) {
125 | throw new IllegalArgumentException("Runner cannot be found: " + getRunnerAbsolutePath());
126 | }
127 | }
128 |
129 | public static void main(String[] args) {
130 | boolean result = false;
131 | try {
132 | DockerRunnerApplicationMaster appMaster = new DockerRunnerApplicationMaster();
133 | LOG.info("Initializing ApplicationMaster. "
134 | + "yarn.timeline-service.webapp.address"
135 | + " = " + appMaster.appHistoryTrackingUrlBase);
136 | boolean doRun = appMaster.init(args);
137 | if (!doRun) {
138 | System.exit(0);
139 | }
140 | result = appMaster.run();
141 | } catch (Throwable t) {
142 | LOG.fatal("Error running ApplicationMaster", t);
143 | System.exit(1);
144 | }
145 |
146 | if (result) {
147 | LOG.info("Application Master completed successfully. exiting");
148 | System.exit(0);
149 | } else {
150 | LOG.info("Application Master failed. exiting");
151 | System.exit(2);
152 | }
153 | }
154 |
155 | private boolean run() throws IOException, YarnException {
156 | LOG.info("Starting ApplicationMaster");
157 | Credentials credentials =
158 | UserGroupInformation.getCurrentUser().getCredentials();
159 | DataOutputBuffer dob = new DataOutputBuffer();
160 | credentials.writeTokenStorageToStream(dob);
161 | // Now remove the AM->RM token so that containers cannot access it.
162 | Iterator> iter = credentials.getAllTokens().iterator();
163 | while (iter.hasNext()) {
164 | Token> token = iter.next();
165 | if (token.getKind().equals(AMRMTokenIdentifier.KIND_NAME)) {
166 | iter.remove();
167 | }
168 | }
169 |
170 | AMRMClientAsync.CallbackHandler allocListener = new RMCallbackHandler();
171 | amRMClient = AMRMClientAsync.createAMRMClientAsync(1000, allocListener);
172 | amRMClient.init(conf);
173 | amRMClient.start();
174 |
175 | // Register self with ResourceManager
176 | // This will start heartbeating to the RM
177 | appMasterHostname = NetUtils.getHostname();
178 | RegisterApplicationMasterResponse response = amRMClient
179 | .registerApplicationMaster(appMasterHostname, appMasterRpcPort, appMasterTrackingUrl);
180 | // Dump out information about cluster capability as seen by the
181 | // resource manager
182 | int maxMem = response.getMaximumResourceCapability().getMemory();
183 | LOG.info("Max mem capabililty of resources in this cluster " + maxMem);
184 |
185 | int maxVCores = response.getMaximumResourceCapability().getVirtualCores();
186 | LOG.info("Max vcores capabililty of resources in this cluster " + maxVCores);
187 |
188 | try {
189 | dockerContainerRunner.startContainer(String.format("%s-%s", appAttemptID, jobName));
190 | dockerContainerRunner.waitContainerExit();
191 | }
192 | catch (Exception e) {
193 | LOG.error("dockerContainerRunner exited with exception: " + e.getMessage(), e);
194 | }
195 |
196 | return finish();
197 | }
198 |
199 | /**
200 | * Parse command line options
201 | *
202 | * @param args Command line args
203 | * @return Whether init successful and run should be invoked
204 | * @throws ParseException
205 | * @throws IOException
206 | */
207 | private boolean init(String[] args) throws ParseException {
208 | Options opts = new Options();
209 | opts.addOption("priority", true, "Application Priority. Default 0");
210 | opts.addOption("container_retry", true, "Application container_retry. Default 3");
211 | opts.addOption("image", true, "Docker image to run");
212 | opts.addOption("job_name", true, "Uniq name of this job");
213 | opts.addOption("v", true, "the file needed to be mounted into docker container");
214 | opts.addOption("w", true, "the working dir of docker container ");
215 | opts.addOption("debug", false, "Dump out debug information");
216 | opts.addOption(OptionBuilder.withLongOpt("docker-args").hasArgs().create());
217 | opts.addOption("help", false, "Print usage");
218 | CommandLine cliParser = new GnuParser().parse(opts, args, true);
219 |
220 | //Check whether customer log4j.properties file exists
221 | if (fileExist(log4jPath)) {
222 | try {
223 | Log4jPropertyHelper.updateLog4jConfiguration(
224 | DockerRunnerApplicationMaster.class, log4jPath);
225 | } catch (Exception e) {
226 | LOG.warn("Can not set up custom log4j properties. " + e);
227 | }
228 | }
229 |
230 | if(!cliParser.hasOption("job_name")){
231 | LOG.error("job_name param not found");
232 | return false;
233 | }
234 | jobName = cliParser.getOptionValue("job_name");
235 | if (cliParser.hasOption("help")) {
236 | printUsage(opts);
237 | return false;
238 | }
239 |
240 | if (cliParser.hasOption("debug")) {
241 | dumpOutDebugInfo();
242 | }
243 |
244 | Map envs = System.getenv();
245 | if (!envs.containsKey(ApplicationConstants.Environment.CONTAINER_ID.name())) {
246 | if (cliParser.hasOption("app_attempt_id")) {
247 | String appIdStr = cliParser.getOptionValue("app_attempt_id", "");
248 | appAttemptID = ConverterUtils.toApplicationAttemptId(appIdStr);
249 | } else {
250 | throw new IllegalArgumentException(
251 | "Application Attempt Id not set in the environment");
252 | }
253 | }
254 | else {
255 | ContainerId containerId = ConverterUtils.toContainerId(envs
256 | .get(ApplicationConstants.Environment.CONTAINER_ID.name()));
257 | appAttemptID = containerId.getApplicationAttemptId();
258 | }
259 |
260 | if (!envs.containsKey(ApplicationConstants.APP_SUBMIT_TIME_ENV)) {
261 | throw new RuntimeException(ApplicationConstants.APP_SUBMIT_TIME_ENV
262 | + " not set in the environment");
263 | }
264 | if (!envs.containsKey(ApplicationConstants.Environment.NM_HOST.name())) {
265 | throw new RuntimeException(ApplicationConstants.Environment.NM_HOST.name()
266 | + " not set in the environment");
267 | }
268 | if (!envs.containsKey(ApplicationConstants.Environment.NM_HTTP_PORT.name())) {
269 | throw new RuntimeException(ApplicationConstants.Environment.NM_HTTP_PORT
270 | + " not set in the environment");
271 | }
272 | if (!envs.containsKey(ApplicationConstants.Environment.NM_PORT.name())) {
273 | throw new RuntimeException(ApplicationConstants.Environment.NM_PORT.name()
274 | + " not set in the environment");
275 | }
276 |
277 | LOG.info("Application master for app" + ", appId="
278 | + appAttemptID.getApplicationId().getId() + ", clustertimestamp="
279 | + appAttemptID.getApplicationId().getClusterTimestamp()
280 | + ", attemptId=" + appAttemptID.getAttemptId());
281 |
282 | this.MAX_RETRY_COUNT.set(Integer.parseInt(cliParser.getOptionValue(
283 | "container_retry", "3")));
284 |
285 | dockerImage = cliParser.getOptionValue("image");
286 | checkNotEmpty(dockerImage, "No image argument given");
287 | mountVolume = cliParser.getOptionValue("v");
288 | workDir = cliParser.getOptionValue("w");
289 | commandToRun = cliParser.getArgs();
290 | dockerArgs = cliParser.getOptionValue("docker-args").split(" ");
291 | this.dockerContainerRunner = new DockerContainerRunner(buildYarnDockerClientParam());
292 | return true;
293 | }
294 |
295 | /**
296 | * Dump out contents of $CWD and the environment to stdout for debugging
297 | */
298 | private void dumpOutDebugInfo() {
299 | LOG.info("Dump debug output");
300 | Map envs = System.getenv();
301 | for (Map.Entry env : envs.entrySet()) {
302 | LOG.info("System env: key=" + env.getKey() + ", val=" + env.getValue());
303 | System.out.println("System env: key=" + env.getKey() + ", val="
304 | + env.getValue());
305 | }
306 |
307 | BufferedReader buf = null;
308 | try {
309 | String lines = Shell.WINDOWS ? Shell.execCommand("cmd", "/c", "dir") :
310 | Shell.execCommand("ls", "-al");
311 | buf = new BufferedReader(new StringReader(lines));
312 | String line = "";
313 | while ((line = buf.readLine()) != null) {
314 | LOG.info("System CWD content: " + line);
315 | System.out.println("System CWD content: " + line);
316 | }
317 | } catch (IOException e) {
318 | LOG.warn(e);
319 | } finally {
320 | IOUtils.cleanup(LOG, buf);
321 | }
322 | }
323 |
324 | private boolean finish(){
325 | // When the application completes, it should send a shutdown application
326 | // signal to the RM
327 | LOG.info("Application completed. Signalling shutdown to RM");
328 |
329 | FinalApplicationStatus appStatus;
330 | String appMessage = null;
331 | boolean success = true;
332 | if (dockerContainerRunner.getExitStatus() == 0) {
333 | appStatus = FinalApplicationStatus.SUCCEEDED;
334 | } else {
335 | appStatus = FinalApplicationStatus.FAILED;
336 | appMessage = "Diagnostics." + ", docker Container exited code: " +
337 | dockerContainerRunner.getExitStatus();
338 | success = false;
339 | }
340 |
341 | try {
342 | amRMClient.unregisterApplicationMaster(appStatus, appMessage,
343 | appHistoryTrackingUrlBase + appAttemptID.getApplicationId().toString());
344 | } catch (YarnException ex) {
345 | LOG.error("Failed to unregister application", ex);
346 | } catch (IOException e) {
347 | LOG.error("Failed to unregister application", e);
348 | }
349 |
350 | amRMClient.stop();
351 | return success;
352 | }
353 |
354 | private boolean fileExist(String filePath) {
355 | return new File(filePath).exists();
356 | }
357 |
358 | private void printUsage(Options opts) {
359 | new HelpFormatter().printHelp("[options] command [commandArgs]", opts);
360 | }
361 |
362 | private class RMCallbackHandler implements AMRMClientAsync.CallbackHandler{
363 | public void onContainersCompleted(List list) {
364 | // Nothing to do since we do not require more container
365 | }
366 |
367 | public void onContainersAllocated(List list) {
368 | // Nothing to do since we do not require more container
369 | }
370 |
371 | public void onShutdownRequest() {
372 | done = true;
373 | dockerContainerRunner.stopContainer();
374 | }
375 |
376 | public void onNodesUpdated(List list) {
377 | // Nothing to do since we do not require more container
378 | }
379 |
380 | public float getProgress() {
381 |
382 | return dockerContainerRunner.getProgress();
383 | }
384 |
385 | public void onError(Throwable throwable) {
386 | done = true;
387 | dockerContainerRunner.stopContainer();
388 | amRMClient.stop();
389 | }
390 | }
391 | }
392 |
--------------------------------------------------------------------------------
/distributed-docker-appmaster/src/main/java/com/sogou/dockeronyarn/common/DSConstants.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package com.sogou.dockeronyarn.common;
20 |
21 | import org.apache.hadoop.classification.InterfaceAudience;
22 | import org.apache.hadoop.classification.InterfaceStability;
23 |
24 | /**
25 | * Constants used in both Client and Application Master
26 | */
27 | @InterfaceAudience.Public
28 | @InterfaceStability.Unstable
29 | public class DSConstants {
30 |
31 | /**
32 | * Environment key name pointing to the shell script's location
33 | */
34 | public static final String DISTRIBUTEDSHELLSCRIPTLOCATION = "DISTRIBUTEDSHELLSCRIPTLOCATION";
35 |
36 | /**
37 | * Environment key name denoting the file timestamp for the shell script.
38 | * Used to validate the local resource.
39 | */
40 | public static final String DISTRIBUTEDSHELLSCRIPTTIMESTAMP = "DISTRIBUTEDSHELLSCRIPTTIMESTAMP";
41 |
42 | /**
43 | * Environment key name denoting the file content length for the shell script.
44 | * Used to validate the local resource.
45 | */
46 | public static final String DISTRIBUTEDSHELLSCRIPTLEN = "DISTRIBUTEDSHELLSCRIPTLEN";
47 | }
48 |
--------------------------------------------------------------------------------
/distributed-docker-appmaster/src/main/java/com/sogou/dockeronyarn/common/DistributedDockerConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.common;
2 |
3 | import org.apache.hadoop.conf.Configuration;
4 |
5 | import java.util.Properties;
6 |
7 | /**
8 | * Created by guoshiwei on 15/5/10.
9 | */
10 | public class DistributedDockerConfiguration extends Configuration {
11 | private static String DISTRIBUTED_DOCKER_CONFIGURATION_FILE
12 | = "distributed-docker-site.xml";
13 |
14 | public static String DDOCKER_PREFIX = "ddocker.";
15 | public static String DDOCKER_RUNNER_PATH = DDOCKER_PREFIX + "runner.path";
16 |
17 | public static final String CONTAINER_MEMORY = DDOCKER_PREFIX + "container.memeory";
18 | public static final int DEFAULT_CONTAINER_MEMORY = 512; // MB
19 |
20 | public static final String CONTAINER_CORES = DDOCKER_PREFIX + "container.cores";
21 | public static final int DEFAULT_CONTAINER_CORES = 1;
22 |
23 | public static final String DOCKER_CERT_PATH = DDOCKER_PREFIX + "docker.cert.path";
24 |
25 | public static final String DOCKER_HOST = DDOCKER_PREFIX + "docker.host";
26 | public static final String DEFAULT_DOCKER_HOST = "127.0.0.1:2376";
27 |
28 | public static final String REQUIRED_RESOURCE_HDFS_PATH = DDOCKER_PREFIX + "resources.hdfs.dir.path";
29 | static {
30 | Configuration.addDefaultResource(DISTRIBUTED_DOCKER_CONFIGURATION_FILE);
31 | }
32 |
33 | /**
34 | * Load system properties which startswith `DDOCKER_PREFIX`
35 | */
36 | public void loadSystemProperties(){
37 | final Properties properties = System.getProperties();
38 | for(String p: properties.stringPropertyNames()){
39 | if(p.startsWith(DDOCKER_PREFIX)){
40 | set(p, properties.getProperty(p));
41 | }
42 | }
43 | }
44 |
45 | public DistributedDockerConfiguration() {
46 | super();
47 | loadSystemProperties();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/distributed-docker-appmaster/src/main/java/com/sogou/dockeronyarn/common/ExitCode.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.common;
2 |
3 | public enum ExitCode{
4 |
5 | CONTAINER_NOT_CREATE(254), ILLEGAL_ARGUMENT(253), FAIL(1), SUCC(0), TIMEOUT(250), KILLED(255);
6 | private int value;
7 | public int getValue() {
8 | return value;
9 | }
10 | public void setValue(int value) {
11 | this.value = value;
12 | }
13 | private ExitCode(int value){
14 | this.value = value;
15 | }
16 |
17 | }
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/distributed-docker-appmaster/src/main/java/com/sogou/dockeronyarn/common/Log4jPropertyHelper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package com.sogou.dockeronyarn.common;
20 |
21 | import java.io.FileInputStream;
22 | import java.io.InputStream;
23 | import java.util.Map.Entry;
24 | import java.util.Properties;
25 |
26 | import org.apache.commons.io.IOUtils;
27 | import org.apache.log4j.LogManager;
28 | import org.apache.log4j.PropertyConfigurator;
29 |
30 |
31 | public class Log4jPropertyHelper {
32 |
33 | public static void updateLog4jConfiguration(Class> targetClass,
34 | String log4jPath) throws Exception {
35 | Properties customProperties = new Properties();
36 | FileInputStream fs = null;
37 | InputStream is = null;
38 | try {
39 | fs = new FileInputStream(log4jPath);
40 | is = targetClass.getResourceAsStream("/log4j.properties");
41 | customProperties.load(fs);
42 | Properties originalProperties = new Properties();
43 | originalProperties.load(is);
44 | for (Entry
87 | *
88 | *
This client is meant to act as an example on how to write yarn-based applications.
89 | *
90 | *
To submit an application, a client first needs to connect to the ResourceManager
91 | * aka ApplicationsManager or ASM via the {@link ApplicationClientProtocol}. The {@link ApplicationClientProtocol}
92 | * provides a way for the client to get access to cluster information and to request for a
93 | * new {@link ApplicationId}.
94 | *
95 | *
For the actual job submission, the client first has to create an {@link ApplicationSubmissionContext}.
96 | * The {@link ApplicationSubmissionContext} defines the application details such as {@link ApplicationId}
97 | * and application name, the priority assigned to the application and the queue
98 | * to which this application needs to be assigned. In addition to this, the {@link ApplicationSubmissionContext}
99 | * also defines the {@link ContainerLaunchContext} which describes the Container with which
100 | * the {@link DockerApplicationMaster_23} is launched.
101 | *
102 | *
The {@link ContainerLaunchContext} in this scenario defines the resources to be allocated for the
103 | * {@link DockerApplicationMaster_23}'s container, the local resources (jars, configuration files) to be made available
104 | * and the environment to be set for the {@link DockerApplicationMaster_23} and the commands to be executed to run the
105 | * {@link DockerApplicationMaster_23}.
106 | *
107 | *
Using the {@link ApplicationSubmissionContext}, the client submits the application to the
108 | * ResourceManager and then monitors the application by requesting the ResourceManager
109 | * for an {@link ApplicationReport} at regular time intervals. In case of the application taking too long, the client
110 | * kills the application by submitting a {@link KillApplicationRequest} to the ResourceManager.
111 | *
112 | */
113 | @InterfaceAudience.Public
114 | @InterfaceStability.Unstable
115 | public class DockerClient {
116 |
117 | private static final Log LOG = LogFactory.getLog(DockerClient.class);
118 |
119 | // Configuration
120 | private Configuration conf;
121 | private YarnClient yarnClient;
122 | // Application master specific info to register a new Application with RM/ASM
123 | private String appName = "";
124 | // App master priority
125 | private int amPriority = 0;
126 | // Queue for App master
127 | private String amQueue = "";
128 | // Amt. of memory resource to request for to run the App Master
129 | private int amMemory = 10;
130 | // Amt. of virtual core resource to request for to run the App Master
131 | private int amVCores = 1;
132 |
133 | private int container_retry = 3;
134 |
135 | // Application master jar file
136 | private String appMasterJar = "";
137 | // Main class to invoke application master
138 | private final String appMasterMainClass;
139 |
140 | // Shell command to be executed
141 | // private String shellCommand = "";
142 | // Location of shell script
143 | //private String shellScriptPath = "";
144 | // Args to be passed to the shell command
145 | private String[] shellArgs = new String[] {};
146 | // Env variables to be setup for the shell command
147 | private Map shellEnv = new HashMap();
148 | // Shell Command Container priority
149 | private int shellCmdPriority = 0;
150 |
151 | // Amt of memory to request for container in which shell script will be executed
152 | private int containerMemory = 10;
153 | // Amt. of virtual cores to request for container in which shell script will be executed
154 | private int containerVirtualCores = 1;
155 | // No. of containers in which the shell script needs to be executed
156 | private int numContainers = 1;
157 |
158 | // log4j.properties file
159 | // if available, add to local resources and set into classpath
160 | private String log4jPropFile = "";
161 |
162 | // Start time for client
163 | private final long clientStartTime = System.currentTimeMillis();
164 | // Timeout threshold for client. Kill app after time interval expires.
165 | private long clientTimeout = 600000;
166 |
167 | // flag to indicate whether to keep containers across application attempts.
168 | private boolean keepContainers = false;
169 |
170 | // Debug flag
171 | boolean debugFlag = false;
172 |
173 | // Command line options
174 | private Options opts;
175 |
176 | private static final String shellCommandPath = "shellCommands";
177 | private static final String shellArgsPath = "shellArgs";
178 | private static final String appMasterJarPath = "AppMaster.jar";
179 | // Hardcoded path to custom log_properties
180 | private static final String log4jPath = "log4j.properties";
181 |
182 | public static final String SCRIPT_PATH = "common.sh";
183 |
184 | public YarnClient getYarnClient(){
185 | return this.yarnClient;
186 | }
187 | /**
188 | * @param args Command line arguments
189 | */
190 | public static void main(String[] args) {
191 | boolean result = false;
192 | try {
193 | DockerClient client = new DockerClient();
194 | LOG.info("Initializing Client");
195 | try {
196 | boolean doRun = client.init(args);
197 | if (!doRun) {
198 | System.exit(0);
199 | }
200 | } catch (IllegalArgumentException e) {
201 | System.err.println(e.getLocalizedMessage());
202 | client.printUsage();
203 | System.exit(-1);
204 | }
205 | //result = client.run();
206 | } catch (Throwable t) {
207 | LOG.fatal("Error running CLient", t);
208 | System.exit(1);
209 | }
210 | if (result) {
211 | LOG.info("Application completed successfully");
212 | System.exit(0);
213 | }
214 | LOG.error("Application failed to complete successfully");
215 | System.exit(2);
216 | }
217 |
218 |
219 |
220 | /**
221 | */
222 | public DockerClient(Configuration conf) throws Exception {
223 | this(
224 | "com.sogou.docker.client.DockerRunnerApplicationMaster",
225 | conf);
226 | }
227 |
228 | DockerClient(String appMasterMainClass, Configuration conf) {
229 | this.conf = conf;
230 | this.appMasterMainClass = appMasterMainClass;
231 | yarnClient = YarnClient.createYarnClient();
232 | yarnClient.init(conf);
233 | opts = new Options();
234 | opts.addOption("appname", true, "Application Name. Default value - DistributedShell");
235 | opts.addOption("priority", true, "Application Priority. Default 0");
236 | opts.addOption("queue", true, "RM Queue in which this application is to be submitted");
237 | opts.addOption("timeout", true, "Application timeout in milliseconds");
238 | opts.addOption("master_memory", true, "Amount of memory in MB to be requested to run the application master");
239 | opts.addOption("master_vcores", true, "Amount of virtual cores to be requested to run the application master");
240 | opts.addOption("jar", true, "Jar file containing the application master");
241 | opts.addOption("shell_command", true, "Shell command to be executed by " +
242 | "the Application Master. Can only specify either --shell_command " +
243 | "or --shell_script");
244 | opts.addOption("shell_script", true, "Location of the shell script to be " +
245 | "executed. Can only specify either --shell_command or --shell_script");
246 | opts.addOption("shell_args", true, "Command line args for the shell script." +
247 | "Multiple args can be separated by empty space.");
248 | opts.getOption("shell_args").setArgs(Option.UNLIMITED_VALUES);
249 | opts.addOption("shell_env", true, "Environment for shell script. Specified as env_key=env_val pairs");
250 | opts.addOption("shell_cmd_priority", true, "Priority for the shell command containers");
251 | opts.addOption("container_memory", true, "Amount of memory in MB to be requested to run the shell command");
252 | opts.addOption("container_vcores", true, "Amount of virtual cores to be requested to run the shell command");
253 | opts.addOption("num_containers", true, "No. of containers on which the shell command needs to be executed");
254 | opts.addOption("log_properties", true, "log4j.properties file");
255 | opts.addOption("container_retry", true, "container retry count");
256 | opts.addOption("keep_containers_across_application_attempts", false,
257 | "Flag to indicate whether to keep containers across application attempts." +
258 | " If the flag is true, running containers will not be killed when" +
259 | " application attempt fails and these containers will be retrieved by" +
260 | " the new application attempt ");
261 | opts.addOption("debug", false, "Dump out debug information");
262 | opts.addOption("help", false, "Print usage");
263 |
264 | }
265 |
266 | /**
267 | */
268 | public DockerClient() throws Exception {
269 | this(new YarnConfiguration());
270 | }
271 |
272 | /**
273 | * Helper function to print out usage
274 | */
275 | public void printUsage() {
276 | new HelpFormatter().printHelp("Client", opts);
277 | }
278 |
279 | /**
280 | * Parse command line options
281 | * @param args Parsed command line options
282 | * @return Whether the init was successful to run the client
283 | * @throws ParseException
284 | */
285 | public boolean init(String[] args) throws ParseException {
286 |
287 | CommandLine cliParser = new GnuParser().parse(opts, args);
288 |
289 | if (args.length == 0) {
290 | throw new IllegalArgumentException("No args specified for client to initialize");
291 | }
292 |
293 | if (cliParser.hasOption("log_properties")) {
294 | String log4jPath = cliParser.getOptionValue("log_properties");
295 | try {
296 | Log4jPropertyHelper.updateLog4jConfiguration(DockerClient.class, log4jPath);
297 | } catch (Exception e) {
298 | LOG.warn("Can not set up custom log4j properties. " + e);
299 | }
300 | }
301 |
302 | if (cliParser.hasOption("help")) {
303 | printUsage();
304 | return false;
305 | }
306 |
307 | if (cliParser.hasOption("debug")) {
308 | debugFlag = true;
309 |
310 | }
311 |
312 | if (cliParser.hasOption("keep_containers_across_application_attempts")) {
313 | LOG.info("keep_containers_across_application_attempts");
314 | keepContainers = true;
315 | }
316 |
317 | appName = cliParser.getOptionValue("appname", "DistributedShell");
318 | amPriority = Integer.parseInt(cliParser.getOptionValue("priority", "0"));
319 | amQueue = cliParser.getOptionValue("queue", "default");
320 | amMemory = Integer.parseInt(cliParser.getOptionValue("master_memory", "10"));
321 | amVCores = Integer.parseInt(cliParser.getOptionValue("master_vcores", "1"));
322 |
323 | container_retry = Integer.parseInt(cliParser.getOptionValue("container_retry", "3"));
324 |
325 | if (amMemory < 0) {
326 | throw new IllegalArgumentException("Invalid memory specified for application master, exiting."
327 | + " Specified memory=" + amMemory);
328 | }
329 | if (amVCores < 0) {
330 | throw new IllegalArgumentException("Invalid virtual cores specified for application master, exiting."
331 | + " Specified virtual cores=" + amVCores);
332 | }
333 |
334 | if (!cliParser.hasOption("jar")) {
335 | throw new IllegalArgumentException("No jar file specified for application master");
336 | }
337 |
338 | appMasterJar = cliParser.getOptionValue("jar");
339 |
340 | if (cliParser.hasOption("shell_args")) {
341 | shellArgs = cliParser.getOptionValues("shell_args");
342 | }
343 | if (cliParser.hasOption("shell_env")) {
344 | String envs[] = cliParser.getOptionValues("shell_env");
345 | for (String env : envs) {
346 | env = env.trim();
347 | int index = env.indexOf('=');
348 | if (index == -1) {
349 | shellEnv.put(env, "");
350 | continue;
351 | }
352 | String key = env.substring(0, index);
353 | String val = "";
354 | if (index < (env.length()-1)) {
355 | val = env.substring(index+1);
356 | }
357 | shellEnv.put(key, val);
358 | }
359 | }
360 | shellCmdPriority = Integer.parseInt(cliParser.getOptionValue("shell_cmd_priority", "0"));
361 |
362 | containerMemory = Integer.parseInt(cliParser.getOptionValue("container_memory", "10"));
363 | containerVirtualCores = Integer.parseInt(cliParser.getOptionValue("container_vcores", "1"));
364 | numContainers = Integer.parseInt(cliParser.getOptionValue("num_containers", "1"));
365 |
366 | if (containerMemory < 0 || containerVirtualCores < 0 || numContainers < 1) {
367 | throw new IllegalArgumentException("Invalid no. of containers or container memory/vcores specified,"
368 | + " exiting."
369 | + " Specified containerMemory=" + containerMemory
370 | + ", containerVirtualCores=" + containerVirtualCores
371 | + ", numContainer=" + numContainers);
372 | }
373 |
374 | clientTimeout = Integer.parseInt(cliParser.getOptionValue("timeout", "600000"));
375 |
376 | log4jPropFile = cliParser.getOptionValue("log_properties", "");
377 |
378 | return true;
379 | }
380 |
381 | /**
382 | * Main run function for the client
383 | * @return true if application completed successfully
384 | * @throws IOException
385 | * @throws YarnException
386 | */
387 | public ApplicationId run() throws IOException, YarnException {
388 |
389 | LOG.info("Running Client");
390 | yarnClient.start();
391 |
392 | YarnClusterMetrics clusterMetrics = yarnClient.getYarnClusterMetrics();
393 | LOG.info("Got Cluster metric info from ASM"
394 | + ", numNodeManagers=" + clusterMetrics.getNumNodeManagers());
395 |
396 | List clusterNodeReports = yarnClient.getNodeReports(
397 | NodeState.RUNNING);
398 | LOG.info("Got Cluster node info from ASM");
399 | for (NodeReport node : clusterNodeReports) {
400 | LOG.info("Got node report from ASM for"
401 | + ", nodeId=" + node.getNodeId()
402 | + ", nodeAddress" + node.getHttpAddress()
403 | + ", nodeRackName" + node.getRackName()
404 | + ", nodeNumContainers" + node.getNumContainers());
405 | }
406 |
407 | QueueInfo queueInfo = yarnClient.getQueueInfo(this.amQueue);
408 | LOG.info("Queue info"
409 | + ", queueName=" + queueInfo.getQueueName()
410 | + ", queueCurrentCapacity=" + queueInfo.getCurrentCapacity()
411 | + ", queueMaxCapacity=" + queueInfo.getMaximumCapacity()
412 | + ", queueApplicationCount=" + queueInfo.getApplications().size()
413 | + ", queueChildQueueCount=" + queueInfo.getChildQueues().size());
414 |
415 | List listAclInfo = yarnClient.getQueueAclsInfo();
416 | for (QueueUserACLInfo aclInfo : listAclInfo) {
417 | for (QueueACL userAcl : aclInfo.getUserAcls()) {
418 | LOG.info("User ACL Info for Queue"
419 | + ", queueName=" + aclInfo.getQueueName()
420 | + ", userAcl=" + userAcl.name());
421 | }
422 | }
423 |
424 | // Get a new application id
425 | YarnClientApplication app = yarnClient.createApplication();
426 | GetNewApplicationResponse appResponse = app.getNewApplicationResponse();
427 | // TODO get min/max resource capabilities from RM and change memory ask if needed
428 | // If we do not have min/max, we may not be able to correctly request
429 | // the required resources from the RM for the app master
430 | // Memory ask has to be a multiple of min and less than max.
431 | // Dump out information about cluster capability as seen by the resource manager
432 | int maxMem = appResponse.getMaximumResourceCapability().getMemory();
433 | LOG.info("Max mem capabililty of resources in this cluster " + maxMem);
434 |
435 | // A resource ask cannot exceed the max.
436 | if (amMemory > maxMem) {
437 | LOG.info("AM memory specified above max threshold of cluster. Using max value."
438 | + ", specified=" + amMemory
439 | + ", max=" + maxMem);
440 | amMemory = maxMem;
441 | }
442 |
443 | int maxVCores = appResponse.getMaximumResourceCapability().getVirtualCores();
444 | LOG.info("Max virtual cores capabililty of resources in this cluster " + maxVCores);
445 |
446 | if (amVCores > maxVCores) {
447 | LOG.info("AM virtual cores specified above max threshold of cluster. "
448 | + "Using max value." + ", specified=" + amVCores
449 | + ", max=" + maxVCores);
450 | amVCores = maxVCores;
451 | }
452 |
453 | // set the application name
454 | ApplicationSubmissionContext appContext = app.getApplicationSubmissionContext();
455 | ApplicationId appId = appContext.getApplicationId();
456 |
457 | //appContext.setKeepContainersAcrossApplicationAttempts(keepContainers);
458 | appContext.setApplicationName(appName);
459 |
460 | // set local resources for the application master
461 | // local files or archives as needed
462 | // In this scenario, the jar file for the application master is part of the local resources
463 | Map localResources = new HashMap();
464 |
465 | LOG.info("Copy App Master jar from local filesystem and add to local environment");
466 | // Copy the application master jar to the filesystem
467 | // Create a local resource to point to the destination jar path
468 | FileSystem fs = FileSystem.get(conf);
469 | addToLocalResources(fs, appMasterJar, appMasterJarPath, appId.toString(),
470 | localResources, null);
471 |
472 | // Set the log4j properties if needed
473 | if (!log4jPropFile.isEmpty()) {
474 | addToLocalResources(fs, log4jPropFile, log4jPath, appId.toString(),
475 | localResources, null);
476 | }
477 |
478 | // The shell script has to be made available on the final container(s)
479 | // where it will be executed.
480 | // To do this, we need to first copy into the filesystem that is visible
481 | // to the yarn framework.
482 | // We do not need to set this as a local resource for the application
483 | // master as the application master does not need it.
484 | String hdfsShellScriptLocation = "";
485 | long hdfsShellScriptLen = 0;
486 | long hdfsShellScriptTimestamp = 0;
487 | //if (!shellScriptPath.isEmpty()) {
488 | // Path shellSrc = new Path(fs.getHomeDirectory(), SCRIPT_PATH);
489 | String shellPathSuffix = SCRIPT_PATH;
490 | Path shellDst =
491 | new Path(fs.getHomeDirectory(), shellPathSuffix);
492 | //fs.copyFromLocalFile(false, true, shellSrc, shellDst);
493 | hdfsShellScriptLocation = shellDst.toUri().toString();
494 | FileStatus shellFileStatus = fs.getFileStatus(shellDst);
495 | hdfsShellScriptLen = shellFileStatus.getLen();
496 | hdfsShellScriptTimestamp = shellFileStatus.getModificationTime();
497 | //}
498 |
499 | if (shellArgs.length > 0) {
500 | addToLocalResources(fs, null, shellArgsPath, appId.toString(),
501 | localResources, StringUtils.join(shellArgs, " "));
502 | }
503 |
504 | // Set the necessary security tokens as needed
505 | //amContainer.setContainerTokens(containerToken);
506 |
507 | // Set the env variables to be setup in the env where the application master will be run
508 | LOG.info("Set the environment for the application master");
509 | Map env = new HashMap();
510 |
511 | // put location of shell script into env
512 | // using the env info, the application master will create the correct local resource for the
513 | // eventual containers that will be launched to execute the shell scripts
514 | env.put(DSConstants.DISTRIBUTEDSHELLSCRIPTLOCATION, hdfsShellScriptLocation);
515 | env.put(DSConstants.DISTRIBUTEDSHELLSCRIPTTIMESTAMP, Long.toString(hdfsShellScriptTimestamp));
516 | env.put(DSConstants.DISTRIBUTEDSHELLSCRIPTLEN, Long.toString(hdfsShellScriptLen));
517 |
518 | // Add AppMaster.jar location to classpath
519 | // At some point we should not be required to add
520 | // the hadoop specific classpaths to the env.
521 | // It should be provided out of the box.
522 | // For now setting all required classpaths including
523 | // the classpath to "." for the application jar
524 | StringBuilder classPathEnv = new StringBuilder(Environment.CLASSPATH.$())
525 | .append(File.pathSeparatorChar).append("./*");
526 |
527 | // StringBuilder classPathEnv = new StringBuilder(Environment.CLASSPATH.$$())
528 | // .append(ApplicationConstants.CLASS_PATH_SEPARATOR).append("./*");
529 |
530 | for (String c : conf.getStrings(
531 | YarnConfiguration.YARN_APPLICATION_CLASSPATH,
532 | YarnConfiguration.DEFAULT_YARN_APPLICATION_CLASSPATH)) {
533 | classPathEnv.append(File.pathSeparatorChar);
534 | classPathEnv.append(c.trim());
535 | }
536 | classPathEnv.append(File.pathSeparatorChar).append("./log4j.properties");
537 |
538 | // for (String c : conf.getStrings(
539 | // YarnConfiguration.YARN_APPLICATION_CLASSPATH,
540 | // YarnConfiguration.DEFAULT_YARN_CROSS_PLATFORM_APPLICATION_CLASSPATH)) {
541 | // classPathEnv.append(ApplicationConstants.CLASS_PATH_SEPARATOR);
542 | // classPathEnv.append(c.trim());
543 | // }
544 | // classPathEnv.append(ApplicationConstants.CLASS_PATH_SEPARATOR).append(
545 | // "./log4j.properties");
546 |
547 | // add the runtime classpath needed for tests to work
548 | if (conf.getBoolean(YarnConfiguration.IS_MINI_YARN_CLUSTER, false)) {
549 | classPathEnv.append(':');
550 | classPathEnv.append(System.getProperty("java.class.path"));
551 | }
552 |
553 | env.put("CLASSPATH", classPathEnv.toString());
554 |
555 | // Set the necessary command to execute the application master
556 | Vector vargs = new Vector(30);
557 |
558 | // Set java executable command
559 | LOG.info("Setting up app master command");
560 | vargs.add(Environment.JAVA_HOME.$() + "/bin/java");
561 | //vargs.add(Environment.JAVA_HOME.$$() + "/bin/java");
562 | // Set Xmx based on am memory size
563 | vargs.add("-Xmx" + amMemory + "m");
564 | // Set class name
565 | vargs.add(appMasterMainClass);
566 | // Set params for Application Master
567 | vargs.add("--container_memory " + String.valueOf(containerMemory));
568 | vargs.add("--container_vcores " + String.valueOf(containerVirtualCores));
569 | vargs.add("--num_containers " + String.valueOf(numContainers));
570 | vargs.add("--priority " + String.valueOf(shellCmdPriority));
571 | vargs.add("--container_retry " + String.valueOf(this.container_retry));
572 |
573 | for (Map.Entry entry : shellEnv.entrySet()) {
574 | vargs.add("--shell_env " + entry.getKey() + "=" + entry.getValue());
575 | }
576 | if (debugFlag) {
577 | vargs.add("--debug");
578 | }
579 |
580 | vargs.add("1>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/AppMaster.stdout");
581 | vargs.add("2>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/AppMaster.stderr");
582 |
583 | // Get final commmand
584 | StringBuilder command = new StringBuilder();
585 | for (CharSequence str : vargs) {
586 | command.append(str).append(" ");
587 | }
588 |
589 | LOG.info("Completed setting up app master command " + command.toString());
590 | List commands = new ArrayList();
591 | commands.add(command.toString());
592 |
593 | // Set up the container launch context for the application master
594 | ContainerLaunchContext amContainer = ContainerLaunchContext.newInstance(
595 | localResources, env, commands, null, null, null);
596 |
597 | // Set up resource type requirements
598 | // For now, both memory and vcores are supported, so we set memory and
599 | // vcores requirements
600 | Resource capability = Resource.newInstance(amMemory, amVCores);
601 | appContext.setResource(capability);
602 |
603 | // Service data is a binary blob that can be passed to the application
604 | // Not needed in this scenario
605 | // amContainer.setServiceData(serviceData);
606 |
607 | // Setup security tokens
608 | if (UserGroupInformation.isSecurityEnabled()) {
609 | // Note: Credentials class is marked as LimitedPrivate for HDFS and MapReduce
610 | Credentials credentials = new Credentials();
611 | String tokenRenewer = conf.get(YarnConfiguration.RM_PRINCIPAL);
612 | if (tokenRenewer == null || tokenRenewer.length() == 0) {
613 | throw new IOException(
614 | "Can't get Master Kerberos principal for the RM to use as renewer");
615 | }
616 |
617 | // For now, only getting tokens for the default file-system.
618 | final Token> tokens[] =
619 | fs.addDelegationTokens(tokenRenewer, credentials);
620 | if (tokens != null) {
621 | for (Token> token : tokens) {
622 | LOG.info("Got dt for " + fs.getUri() + "; " + token);
623 | }
624 | }
625 | DataOutputBuffer dob = new DataOutputBuffer();
626 | credentials.writeTokenStorageToStream(dob);
627 | ByteBuffer fsTokens = ByteBuffer.wrap(dob.getData(), 0, dob.getLength());
628 | amContainer.setTokens(fsTokens);
629 | }
630 |
631 | appContext.setAMContainerSpec(amContainer);
632 |
633 | // Set the priority for the application master
634 | // TODO - what is the range for priority? how to decide?
635 | Priority pri = Priority.newInstance(amPriority);
636 | appContext.setPriority(pri);
637 |
638 | // Set the queue to which this application is to be submitted in the RM
639 | appContext.setQueue(amQueue);
640 |
641 | // Submit the application to the applications manager
642 | // SubmitApplicationResponse submitResp = applicationsManager.submitApplication(appRequest);
643 | // Ignore the response as either a valid response object is returned on success
644 | // or an exception thrown to denote some form of a failure
645 | LOG.info("Submitting application to ASM");
646 |
647 | yarnClient.submitApplication(appContext);
648 |
649 | // TODO
650 | // Try submitting the same request again
651 | // app submission failure?
652 |
653 | // Monitor the application
654 | return appId;
655 |
656 | }
657 |
658 | /**
659 | * Monitor the submitted application for completion.
660 | * Kill application if time expires.
661 | * @param appId Application Id of application to be monitored
662 | * @return true if application completed successfully
663 | * @throws YarnException
664 | * @throws IOException
665 | */
666 | private boolean monitorApplication(ApplicationId appId)
667 | throws YarnException, IOException {
668 |
669 | while (true) {
670 |
671 | // Check app status every 1 second.
672 | try {
673 | Thread.sleep(1000);
674 | } catch (InterruptedException e) {
675 | LOG.debug("Thread sleep in monitoring loop interrupted");
676 | }
677 | // Get application report for the appId we are interested in
678 | ApplicationReport report = yarnClient.getApplicationReport(appId);
679 |
680 | LOG.info("Got application report from ASM for"
681 | + ", appId=" + appId.getId()
682 | + ", clientToAMToken=" + report.getClientToAMToken()
683 | + ", appDiagnostics=" + report.getDiagnostics()
684 | + ", appMasterHost=" + report.getHost()
685 | + ", appQueue=" + report.getQueue()
686 | + ", appMasterRpcPort=" + report.getRpcPort()
687 | + ", appStartTime=" + report.getStartTime()
688 | + ", yarnAppState=" + report.getYarnApplicationState().toString()
689 | + ", distributedFinalState=" + report.getFinalApplicationStatus().toString()
690 | + ", appTrackingUrl=" + report.getTrackingUrl()
691 | + ", appUser=" + report.getUser());
692 |
693 | YarnApplicationState state = report.getYarnApplicationState();
694 | FinalApplicationStatus dsStatus = report.getFinalApplicationStatus();
695 | if (YarnApplicationState.FINISHED == state) {
696 | if (FinalApplicationStatus.SUCCEEDED == dsStatus) {
697 | LOG.info("Application has completed successfully. Breaking monitoring loop");
698 | return true;
699 | }
700 | else {
701 | LOG.info("Application did finished unsuccessfully."
702 | + " YarnState=" + state.toString() + ", DSFinalStatus=" + dsStatus.toString()
703 | + ". Breaking monitoring loop");
704 | return false;
705 | }
706 | }
707 | else if (YarnApplicationState.KILLED == state
708 | || YarnApplicationState.FAILED == state) {
709 | LOG.info("Application did not shutdown."
710 | + " YarnState=" + state.toString() + ", DSFinalStatus=" + dsStatus.toString()
711 | + ". Breaking monitoring loop");
712 | return false;
713 | }
714 |
715 | if (System.currentTimeMillis() > (clientStartTime + clientTimeout)) {
716 | LOG.info("Reached client specified timeout for application. Killing application");
717 | forceKillApplication(appId);
718 | return false;
719 | }
720 | }
721 |
722 | }
723 |
724 | /**
725 | * Kill a submitted application by sending a call to the ASM
726 | * @param appId Application Id to be killed.
727 | * @throws YarnException
728 | * @throws IOException
729 | */
730 | private void forceKillApplication(ApplicationId appId)
731 | throws YarnException, IOException {
732 | // TODO clarify whether multiple jobs with the same app id can be submitted and be running at
733 | // the same time.
734 | // If yes, can we kill a particular attempt only?
735 |
736 | // Response can be ignored as it is non-null on success or
737 | // throws an exception in case of failures
738 | yarnClient.killApplication(appId);
739 | }
740 |
741 | private void addToLocalResources(FileSystem fs, String fileSrcPath,
742 | String fileDstPath, String appId, Map localResources,
743 | String resources) throws IOException {
744 | String suffix =
745 | appName + "/" + appId + "/" + fileDstPath;
746 | Path dst =
747 | new Path(fs.getHomeDirectory(), suffix);
748 | if (fileSrcPath == null) {
749 | FSDataOutputStream ostream = null;
750 | try {
751 | ostream = FileSystem
752 | .create(fs, dst, new FsPermission((short) 0710));
753 | ostream.writeUTF(resources);
754 | } finally {
755 | IOUtils.closeQuietly(ostream);
756 | }
757 | } else {
758 | fs.copyFromLocalFile(new Path(fileSrcPath), dst);
759 | }
760 | FileStatus scFileStatus = fs.getFileStatus(dst);
761 | LocalResource scRsrc =
762 | LocalResource.newInstance(
763 | ConverterUtils.getYarnUrlFromURI(dst.toUri()),
764 | LocalResourceType.FILE, LocalResourceVisibility.APPLICATION,
765 | scFileStatus.getLen(), scFileStatus.getModificationTime());
766 | localResources.put(fileDstPath, scRsrc);
767 | }
768 | }
769 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/java/com/sogou/dockeronyarn/client/DockerOnYarnAppDescriptor.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.client;
2 |
3 | /**
4 | * Created by guoshiwei on 15/5/16.
5 | */
6 | public class DockerOnYarnAppDescriptor {
7 | // Start time for client
8 | private final long clientStartTime = System.currentTimeMillis();
9 |
10 | public String[] getDockerArgs() {
11 | return dockerArgs;
12 | }
13 |
14 | public DockerOnYarnAppDescriptor setDockerArgs(String[] dockerArgs) {
15 | this.dockerArgs = dockerArgs;
16 | return this ;
17 | }
18 |
19 | // Application master specific info to register a new Application with RM/ASM
20 | private String appName = "";
21 | // App master priority
22 | private int amPriority = 0;
23 |
24 | private String[] dockerArgs = {};
25 | // Queue for App master
26 |
27 | public String getMemory() {
28 | return memory;
29 | }
30 |
31 | public DockerOnYarnAppDescriptor setMemory(String memory) {
32 | this.memory = memory;
33 | return this ;
34 | }
35 |
36 | public String getCpuShares() {
37 | return cpuShares;
38 | }
39 |
40 | public DockerOnYarnAppDescriptor setCpuShares(String cpuShares) {
41 | this.cpuShares = cpuShares;
42 | return this ;
43 | }
44 |
45 | private String amQueue = "";
46 |
47 | // log4j.properties file
48 | // if available, add to local resources and set into classpath
49 | private String log4jPropFile = "";
50 | private long clientTimeout;
51 | private String dockerImage;
52 | private int container_retry = 3;
53 | private String memory ="";
54 | private String cpuShares="" ;
55 |
56 |
57 | private String workDir ="";
58 |
59 | public String getWorkDir() {
60 | return workDir;
61 | }
62 |
63 | public DockerOnYarnAppDescriptor setWorkDir(String workDir) {
64 | this.workDir = workDir;
65 | return this;
66 | }
67 |
68 | private String mountVolume;
69 |
70 | public String getMountVolume() {
71 | return mountVolume;
72 | }
73 |
74 | public void setMountVolume(String mountVolume) {
75 | this.mountVolume = mountVolume;
76 | }
77 |
78 | public String getAmJarPath() {
79 | return amJarPath;
80 | }
81 |
82 | public DockerOnYarnAppDescriptor setAmJarPath(String amJarPath) {
83 | this.amJarPath = amJarPath;
84 | return this ;
85 | }
86 |
87 | private String commandToRun;
88 | private String amJarPath ;
89 |
90 | public DockerOnYarnAppDescriptor setAppName(String appName) {
91 | this.appName = appName;
92 | return this;
93 | }
94 |
95 | public DockerOnYarnAppDescriptor setAmPriority(int amPriority) {
96 | this.amPriority = amPriority; return this;
97 | }
98 |
99 | public DockerOnYarnAppDescriptor setAmQueue(String amQueue) {
100 | this.amQueue = amQueue; return this;
101 | }
102 |
103 | public DockerOnYarnAppDescriptor setContainer_retry(int container_retry) {
104 | this.container_retry = container_retry; return this;
105 | }
106 |
107 | public DockerOnYarnAppDescriptor setLog4jPropFile(String log4jPropFile) {
108 | this.log4jPropFile = log4jPropFile; return this;
109 | }
110 |
111 | public DockerOnYarnAppDescriptor setClientTimeout(long clientTimeout) {
112 | this.clientTimeout = clientTimeout; return this;
113 | }
114 |
115 | public DockerOnYarnAppDescriptor setDockerImage(String dockerImage) {
116 | this.dockerImage = dockerImage; return this;
117 | }
118 |
119 | public DockerOnYarnAppDescriptor setCommandToRun(String commandToRun) {
120 | this.commandToRun = commandToRun; return this;
121 | }
122 |
123 | public long getClientStartTime() {
124 | return clientStartTime;
125 | }
126 |
127 | public String getAppName() {
128 | return appName;
129 | }
130 |
131 | public int getAmPriority() {
132 | return amPriority;
133 | }
134 |
135 | public String getAmQueue() {
136 | return amQueue;
137 | }
138 |
139 | public String getLog4jPropFile() {
140 | return log4jPropFile;
141 | }
142 |
143 | public long getClientTimeout() {
144 | return clientTimeout;
145 | }
146 |
147 | public String getDockerImage() {
148 | return dockerImage;
149 | }
150 |
151 | public int getContainer_retry() {
152 | return container_retry;
153 | }
154 |
155 | public String getCommandToRun() {
156 | return commandToRun;
157 | }
158 |
159 |
160 |
161 | }
162 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/java/com/sogou/dockeronyarn/client/DockerOnYarnClient.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.client;
2 |
3 | import com.google.common.base.Preconditions;
4 | import com.sogou.dockeronyarn.appmaster.DockerRunnerApplicationMaster;
5 | import com.sogou.dockeronyarn.common.DistributedDockerConfiguration;
6 | import org.apache.commons.lang.StringUtils;
7 | import org.apache.commons.logging.Log;
8 | import org.apache.commons.logging.LogFactory;
9 | import org.apache.hadoop.conf.Configuration;
10 | import org.apache.hadoop.fs.FileStatus;
11 | import org.apache.hadoop.fs.FileSystem;
12 | import org.apache.hadoop.fs.Path;
13 | import org.apache.hadoop.io.DataOutputBuffer;
14 | import org.apache.hadoop.security.Credentials;
15 | import org.apache.hadoop.security.UserGroupInformation;
16 | import org.apache.hadoop.yarn.api.ApplicationConstants;
17 | import org.apache.hadoop.yarn.api.records.*;
18 | import org.apache.hadoop.yarn.client.api.YarnClient;
19 | import org.apache.hadoop.yarn.client.api.YarnClientApplication;
20 | import org.apache.hadoop.yarn.conf.YarnConfiguration;
21 | import org.apache.hadoop.yarn.exceptions.YarnException;
22 | import org.apache.hadoop.yarn.util.ConverterUtils;
23 | import org.apache.hadoop.yarn.util.Records;
24 | import org.mortbay.util.StringUtil;
25 |
26 | import java.io.File;
27 | import java.io.IOException;
28 | import java.nio.ByteBuffer;
29 | import java.util.ArrayList;
30 | import java.util.HashMap;
31 | import java.util.List;
32 | import java.util.Map;
33 |
34 | /**
35 | * Created by guoshiwei on 15/4/25.
36 | */
37 | public class DockerOnYarnClient {
38 | private static final Log LOG = LogFactory.getLog(DockerOnYarnClient.class);
39 |
40 | // Configuration
41 | private final Configuration yarnConf;
42 |
43 | private final DistributedDockerConfiguration ddockerConf;
44 | private final YarnClient yarnClient;
45 |
46 | // Hardcoded path to custom log_properties
47 | private static final String log4jHdfsPath = "log4j.properties";
48 |
49 | // Main class to invoke application master
50 | private final String appMasterMainClass;
51 |
52 | private boolean keepContainers;
53 |
54 | private static final String appMasterJarHdfsPath = "AppMaster.jar";
55 |
56 | // Amt. of memory resource to request for to run the App Master
57 | private int amMemory = 10;
58 | // Amt. of virtual core resource to request for to run the App Master
59 | private int amVCores = 1;
60 |
61 | private static final String libDir = "lib";
62 |
63 | private boolean debugFlag;
64 | private FileSystem fs;
65 |
66 | public DockerOnYarnClient() {
67 | this.yarnConf = new YarnConfiguration();
68 | this.ddockerConf = new DistributedDockerConfiguration();
69 | this.appMasterMainClass = DockerRunnerApplicationMaster.class.getName();
70 | yarnClient = YarnClient.createYarnClient();
71 | yarnClient.init(yarnConf);
72 |
73 | }
74 |
75 | private String getAppMasterJarfilePath() {
76 | return null;
77 | }
78 |
79 | public void start() throws IOException, YarnException {
80 | LOG.info("Running Client");
81 | fs = FileSystem.get(yarnConf);
82 | yarnClient.start();
83 | YarnClusterMetrics clusterMetrics = yarnClient.getYarnClusterMetrics();
84 | LOG.info("Got Cluster metric info from ASM"
85 | + ", numNodeManagers=" + clusterMetrics.getNumNodeManagers());
86 |
87 | List clusterNodeReports = yarnClient.getNodeReports(
88 | NodeState.RUNNING);
89 | LOG.info("Got Cluster node info from ASM");
90 | for (NodeReport node : clusterNodeReports) {
91 | LOG.info("Got node report from ASM for"
92 | + ", nodeId=" + node.getNodeId()
93 | + ", nodeAddress" + node.getHttpAddress()
94 | + ", nodeRackName" + node.getRackName()
95 | + ", nodeNumContainers" + node.getNumContainers());
96 | }
97 |
98 | List listAclInfo = yarnClient.getQueueAclsInfo();
99 | for (QueueUserACLInfo aclInfo : listAclInfo) {
100 | for (QueueACL userAcl : aclInfo.getUserAcls()) {
101 | LOG.info("User ACL Info for Queue"
102 | + ", queueName=" + aclInfo.getQueueName()
103 | + ", userAcl=" + userAcl.name());
104 | }
105 | }
106 | }
107 |
108 |
109 | public void stop() {
110 | yarnClient.stop();
111 | }
112 |
113 | /**
114 | * Submit app descripted by @appDescriptor and wait it for shutdown.
115 | */
116 | public boolean run(DockerOnYarnAppDescriptor appDescriptor) throws IOException, YarnException {
117 | // LOG.info("Running Client");
118 | // yarnClient.start();
119 | start();
120 | ApplicationId appId = submitYarnApplication(appDescriptor);
121 | return monitorApplication(appId, appDescriptor);
122 | }
123 |
124 | public ApplicationId submitYarnApplication(DockerOnYarnAppDescriptor appDescriptor) throws IOException, YarnException {
125 |
126 | QueueInfo queueInfo = yarnClient.getQueueInfo(appDescriptor.getAmQueue());
127 | LOG.info("Queue info"
128 | + ", queueName=" + queueInfo.getQueueName()
129 | + ", queueCurrentCapacity=" + queueInfo.getCurrentCapacity()
130 | + ", queueMaxCapacity=" + queueInfo.getMaximumCapacity()
131 | + ", queueApplicationCount=" + queueInfo.getApplications().size()
132 | + ", queueChildQueueCount=" + queueInfo.getChildQueues().size());
133 |
134 | // Get a new application id
135 | YarnClientApplication app = yarnClient.createApplication();
136 |
137 | int maxMem = app.getNewApplicationResponse().getMaximumResourceCapability().getMemory();
138 | LOG.info("Max mem capabililty of resources in this cluster " + maxMem);
139 |
140 | ApplicationSubmissionContext appContext = createApplicationSubmissionContext(appDescriptor, app);
141 |
142 | LOG.info("Submitting application to ASM");
143 | return yarnClient.submitApplication(appContext);
144 | }
145 |
146 | private ApplicationSubmissionContext createApplicationSubmissionContext(
147 | DockerOnYarnAppDescriptor appDescriptor, YarnClientApplication app) throws IOException {
148 | ApplicationSubmissionContext appContext = app.getApplicationSubmissionContext();
149 |
150 | appContext.setApplicationName(appDescriptor.getAppName());
151 | appContext.setPriority(createPriorityRecord(appDescriptor));
152 | appContext.setQueue(appDescriptor.getAmQueue());
153 |
154 | appContext.setAMContainerSpec(createContainerLaunchContext(appDescriptor, appContext));
155 |
156 | return appContext;
157 | }
158 |
159 | private Priority createPriorityRecord(DockerOnYarnAppDescriptor appDescriptor) {
160 | Priority pri = Records.newRecord(Priority.class);
161 | pri.setPriority(appDescriptor.getAmPriority());
162 | return pri;
163 | }
164 |
165 | /**
166 | * Setup required resources for AM.
167 | *
168 | * All required resources should be placed on HDFS first.
169 | * The value of DistributedDockerConfiguration.REQUIRED_RESOURCE_HDFS_PATH will be used.
170 | * You can set a value other than the default one to use different version of AppMaster.
171 | *
172 | * Under REQUIRED_RESOURCE_HDFS_PATH dir, must have the following file structure:
173 | * - lib/appmaster.jar
174 | * - runner.py
175 | * - conf/distributed-docker-default.xml
176 | * - conf/log4j.properties
177 | *
178 | * If a local log4j.properties is given, the default one on hdfs will not be used,
179 | * but the local one will be uploaded every time the app is submitted. Upload every time
180 | * is slow, so we prefer to use the default one.
181 | *
182 | * @param appDescriptor
183 | * @param appId
184 | * @return
185 | * @throws IOException
186 | */
187 | private Map createLocaleResourceMap(
188 | DockerOnYarnAppDescriptor appDescriptor, ApplicationId appId) throws IOException {
189 | Map localResources = new HashMap();
190 |
191 | LOG.info("Copy App Master jar from local filesystem and add to local environment");
192 | // Copy the application master jar to the filesystem
193 | // Create a local resource to point to the destination jar path
194 |
195 | loadLocalResources(appDescriptor.getAmJarPath(), appMasterJarHdfsPath,localResources);
196 |
197 | loadLocalResources(ddockerConf.get(DistributedDockerConfiguration.DDOCKER_RUNNER_PATH),
198 | DockerRunnerApplicationMaster.LOCAL_RUNNER_NAME,localResources);
199 |
200 | // Set the log4j properties if needed
201 | if (!appDescriptor.getLog4jPropFile().isEmpty()) {
202 | addToLocalResources(appDescriptor.getLog4jPropFile(), log4jHdfsPath, appId.toString(),
203 | localResources, appDescriptor);
204 | }
205 | return localResources;
206 | }
207 |
208 | private ContainerLaunchContext createContainerLaunchContext(
209 | DockerOnYarnAppDescriptor appDescriptor,
210 | ApplicationSubmissionContext appContext) throws IOException {
211 | ContainerLaunchContext amContainer = Records.newRecord(ContainerLaunchContext.class);
212 |
213 |
214 | // set local resources for the application master
215 | // local files or archives as needed
216 | // In this scenario, the jar file for the application master is part of the local resources
217 | Map localResources = createLocaleResourceMap(appDescriptor, appContext.getApplicationId());
218 |
219 | amContainer.setLocalResources(localResources);
220 |
221 | // Set the env variables to be setup in the env where the application master will be run
222 | LOG.info("Set the environment for the application master");
223 | Map env = getEnv();
224 |
225 | // env.put("mount.volume",appDescriptor.getMountVolume());
226 |
227 | amContainer.setEnvironment(env);
228 | amContainer.setCommands(getAppMasterCommands(appDescriptor));
229 |
230 | // Set up resource type requirements
231 | // For now, both memory and vcores are supported, so we set memory and
232 | // vcores requirements
233 | Resource capability = Records.newRecord(Resource.class);
234 | capability.setMemory(amMemory);
235 | capability.setVirtualCores(amVCores);
236 | appContext.setResource(capability);
237 |
238 | // Setup security tokens
239 | if (UserGroupInformation.isSecurityEnabled()) {
240 | Credentials credentials = new Credentials();
241 | String tokenRenewer = yarnConf.get(YarnConfiguration.RM_PRINCIPAL);
242 | if (tokenRenewer == null || tokenRenewer.length() == 0) {
243 | throw new IOException(
244 | "Can't get Master Kerberos principal for the RM to use as renewer");
245 | }
246 |
247 | // For now, only getting tokens for the default file-system.
248 | final org.apache.hadoop.security.token.Token> tokens[] =
249 | fs.addDelegationTokens(tokenRenewer, credentials);
250 | if (tokens != null) {
251 | for (org.apache.hadoop.security.token.Token> token : tokens) {
252 | LOG.info("Got dt for " + fs.getUri() + "; " + token);
253 | }
254 | }
255 | DataOutputBuffer dob = new DataOutputBuffer();
256 | credentials.writeTokenStorageToStream(dob);
257 | ByteBuffer fsTokens = ByteBuffer.wrap(dob.getData(), 0, dob.getLength());
258 | amContainer.setTokens(fsTokens);
259 | }
260 | return amContainer;
261 | }
262 |
263 | private List getAppMasterCommands(DockerOnYarnAppDescriptor appDescriptor) {
264 | // Set the necessary command to execute the application master
265 | List vargs = new ArrayList(30);
266 |
267 | // Set java executable command
268 | LOG.info("Setting up app master command");
269 | vargs.add("java");
270 |
271 | // Set Xmx based on am memory size
272 | vargs.add("-Xmx" + amMemory + "m");
273 | // vargs.add("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=12345");
274 |
275 | // Pass DistributedDockerConfiguration as Properties
276 | for (Map.Entry e : ddockerConf) {
277 | if (e.getKey().startsWith(DistributedDockerConfiguration.DDOCKER_PREFIX)) {
278 | vargs.add(String.format("-D%s=%s", e.getKey(), e.getValue()));
279 | }
280 | }
281 |
282 | // Set class name
283 | vargs.add(appMasterMainClass);
284 |
285 | // Set params for Application Master
286 | vargs.add("-job_name");
287 | vargs.add(appDescriptor.getAppName());
288 |
289 |
290 | vargs.add("-v");
291 | vargs.add(appDescriptor.getMountVolume());
292 |
293 | vargs.add("-w");
294 | vargs.add(appDescriptor.getWorkDir());
295 |
296 | vargs.add("--docker-args");
297 | vargs.add("'"+StringUtils.join(appDescriptor.getDockerArgs()," ")+"\'");
298 |
299 | vargs.add("-image");
300 | vargs.add(appDescriptor.getDockerImage());
301 | if (debugFlag) {
302 | vargs.add("--debug");
303 | }
304 |
305 | vargs.add("1>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/AppMaster.stdout");
306 | vargs.add("2>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/AppMaster.stderr");
307 |
308 | vargs.add(appDescriptor.getCommandToRun());
309 |
310 | Object object ;
311 | LOG.info("AppMasterCommand: " + StringUtils.join(vargs, " "));
312 |
313 | return vargs;
314 | }
315 |
316 | private Map getEnv() {
317 | Map env = new HashMap();
318 |
319 | StringBuilder classPathEnv = new StringBuilder("./*");
320 | for (String c : yarnConf.getStrings(
321 | YarnConfiguration.YARN_APPLICATION_CLASSPATH,
322 | YarnConfiguration.DEFAULT_YARN_APPLICATION_CLASSPATH)) {
323 | classPathEnv.append(File.pathSeparatorChar).append(c.trim());
324 | }
325 |
326 | classPathEnv.append(File.pathSeparatorChar).append(
327 | ApplicationConstants.Environment.CLASSPATH.$());
328 |
329 |
330 | // add the runtime classpath needed for tests to work
331 | if (yarnConf.getBoolean(YarnConfiguration.IS_MINI_YARN_CLUSTER, false)) {
332 | classPathEnv.append(':');
333 | classPathEnv.append(System.getProperty("java.class.path"));
334 | }
335 |
336 | env.put("CLASSPATH", classPathEnv.toString());
337 | return env;
338 | }
339 |
340 | public YarnClient getYarnClient() {
341 | return yarnClient;
342 | }
343 |
344 | /**
345 | * Monitor the submitted application for completion.
346 | * Kill application if time expires.
347 | *
348 | * @param appId Application Id of application to be monitored
349 | * @return true if application completed successfully
350 | * @throws YarnException
351 | * @throws IOException
352 | */
353 | public boolean monitorApplication(ApplicationId appId, DockerOnYarnAppDescriptor appDescriptor)
354 | throws YarnException, IOException {
355 |
356 | while (true) {
357 |
358 | // Check app status every 1 second.
359 | try {
360 | Thread.sleep(1000);
361 | } catch (InterruptedException e) {
362 | LOG.debug("Thread sleep in monitoring loop interrupted");
363 | }
364 |
365 | // Get application report for the appId we are interested in
366 | ApplicationReport report = yarnClient.getApplicationReport(appId);
367 |
368 | LOG.info("Got application report from ASM for"
369 | + ", appId=" + appId.getId()
370 | + ", clientToAMToken=" + report.getClientToAMToken()
371 | + ", appDiagnostics=" + report.getDiagnostics()
372 | + ", appMasterHost=" + report.getHost()
373 | + ", appQueue=" + report.getQueue()
374 | + ", appMasterRpcPort=" + report.getRpcPort()
375 | + ", appStartTime=" + report.getStartTime()
376 | + ", yarnAppState=" + report.getYarnApplicationState().toString()
377 | + ", distributedFinalState=" + report.getFinalApplicationStatus().toString()
378 | + ", appTrackingUrl=" + report.getTrackingUrl()
379 | + ", appUser=" + report.getUser());
380 |
381 | YarnApplicationState state = report.getYarnApplicationState();
382 | FinalApplicationStatus dsStatus = report.getFinalApplicationStatus();
383 | if (YarnApplicationState.FINISHED == state) {
384 | if (FinalApplicationStatus.SUCCEEDED == dsStatus) {
385 | LOG.info("Application has completed successfully. Breaking monitoring loop");
386 | return true;
387 | } else {
388 | LOG.info("Application did finished unsuccessfully."
389 | + " YarnState=" + state.toString() + ", DSFinalStatus=" + dsStatus.toString()
390 | + ". Breaking monitoring loop");
391 | return false;
392 | }
393 | } else if (YarnApplicationState.KILLED == state
394 | || YarnApplicationState.FAILED == state) {
395 | LOG.info("Application did not shutdown."
396 | + " YarnState=" + state.toString() + ", DSFinalStatus=" + dsStatus.toString()
397 | + ". Breaking monitoring loop");
398 | return false;
399 | }
400 |
401 | if (System.currentTimeMillis() > (appDescriptor.getClientStartTime() + appDescriptor.getClientTimeout())) {
402 | LOG.info("Reached client specified timeout for application. Killing application");
403 | forceKillApplication(appId);
404 | return false;
405 | }
406 | }
407 |
408 | }
409 |
410 | /**
411 | * Kill a submitted application by sending a call to the ASM
412 | *
413 | * @param appId Application Id to be killed.
414 | * @throws YarnException
415 | * @throws IOException
416 | */
417 | public void forceKillApplication(ApplicationId appId)
418 | throws YarnException, IOException {
419 | // TODO clarify whether multiple jobs with the same app id can be submitted and be running at
420 | // the same time.
421 | // If yes, can we kill a particular attempt only?
422 |
423 | // Response can be ignored as it is non-null on success or
424 | // throws an exception in case of failures
425 | yarnClient.killApplication(appId);
426 | }
427 |
428 | private void addToLocalResources(String fileSrcPath,
429 | String fileDstPath, String appId,
430 | Map localResources,
431 | DockerOnYarnAppDescriptor appDescriptor) throws IOException {
432 | Preconditions.checkNotNull(fileDstPath);
433 |
434 | // TODO Skip upload appMaster resources if it is not changed.
435 | String suffix =
436 | appDescriptor.getAppName() + "/" + appId + "/" + fileDstPath;
437 | Path dst =
438 | new Path(fs.getHomeDirectory(), suffix);
439 |
440 | fs.copyFromLocalFile(new Path(fileSrcPath), dst);
441 |
442 | FileStatus scFileStatus = fs.getFileStatus(dst);
443 | LocalResource scRsrc =
444 | LocalResource.newInstance(
445 | ConverterUtils.getYarnUrlFromURI(dst.toUri()),
446 | LocalResourceType.FILE, LocalResourceVisibility.PUBLIC,
447 | scFileStatus.getLen(), scFileStatus.getModificationTime());
448 | localResources.put(fileDstPath, scRsrc);
449 | }
450 |
451 | public void setDebugFlag(boolean debugFlag) {
452 | this.debugFlag = debugFlag;
453 | }
454 |
455 | private void loadLocalResources(String fileSrcPath,
456 | String fileDstPath,
457 | Map localResources) throws IOException {
458 | Preconditions.checkNotNull(fileDstPath);
459 | String suffix =
460 | libDir + "/" + fileDstPath ;
461 | Path dst =
462 | new Path(fs.getHomeDirectory(),suffix);
463 | if(!fs.exists(dst)){
464 | fs.copyFromLocalFile(new Path(fileSrcPath), dst);
465 | }
466 | FileStatus scFileStatus = fs.getFileStatus(dst);
467 | LocalResource scRsrc =
468 | LocalResource.newInstance(
469 | ConverterUtils.getYarnUrlFromURI(dst.toUri()),
470 | LocalResourceType.FILE, LocalResourceVisibility.PUBLIC,
471 | scFileStatus.getLen(), scFileStatus.getModificationTime());
472 | localResources.put(fileDstPath, scRsrc);
473 | }
474 |
475 |
476 | public ApplicationReport getApplicationReport(ApplicationId appId)
477 | {
478 | try {
479 | return yarnClient.getApplicationReport(appId);
480 | } catch (YarnException e) {
481 | e.printStackTrace();
482 |
483 | } catch (IOException e) {
484 | e.printStackTrace();
485 | }
486 | return null ;
487 | }
488 |
489 | public void killApplication(ApplicationId appId)
490 | throws YarnException, IOException {
491 | // TODO clarify whether multiple jobs with the same app id can be submitted and be running at
492 | // the same time.
493 | // If yes, can we kill a particular attempt only?
494 |
495 | // Response can be ignored as it is non-null on success or
496 | // throws an exception in case of failures
497 | yarnClient.killApplication(appId);
498 | }
499 |
500 |
501 |
502 | }
503 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/java/com/sogou/dockeronyarn/client/DockerOnYarnClientCli.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.client;
2 |
3 | import com.sogou.dockeronyarn.common.Log4jPropertyHelper;
4 | import org.apache.commons.cli.*;
5 | import org.apache.commons.lang.StringUtils;
6 | import org.apache.commons.logging.Log;
7 | import org.apache.commons.logging.LogFactory;
8 |
9 | import static com.sogou.dockeronyarn.common.Utils.checkNotEmpty;
10 |
11 | /**
12 | * Created by guoshiwei on 15/5/16.
13 | */
14 | public class DockerOnYarnClientCli {
15 | private static final Log LOG = LogFactory.getLog(DockerOnYarnClientCli.class);
16 | private final DockerOnYarnClient dockerClient;
17 | private DockerOnYarnAppDescriptor appDescriptor;
18 | private Options opts;
19 | private String amJarPath ;
20 |
21 | public DockerOnYarnClientCli() {
22 | dockerClient = new DockerOnYarnClient();
23 | appDescriptor = new DockerOnYarnAppDescriptor();
24 | this.setupOpts();
25 | }
26 |
27 | public String getAmJarPath() {
28 | return amJarPath;
29 | }
30 |
31 | public void setAmJarPath(String amJarPath) {
32 | this.amJarPath = amJarPath;
33 | }
34 |
35 | public static void main(String [] args){
36 | boolean result = false;
37 | try {
38 | DockerOnYarnClientCli client = new DockerOnYarnClientCli();
39 | LOG.info("Initializing Client");
40 | try {
41 |
42 | boolean doRun = client.init(args);
43 | if (!doRun) {
44 | System.exit(0);
45 | }
46 | } catch (IllegalArgumentException e) {
47 | System.err.println(e.getLocalizedMessage());
48 | client.printUsage();
49 | System.exit(-1);
50 | }
51 | result = client.dockerClient.run(client.appDescriptor);
52 | } catch (Throwable t) {
53 | LOG.fatal("Error running CLient", t);
54 | System.exit(1);
55 | }
56 | if (result) {
57 | LOG.info("Application completed successfully");
58 | System.exit(0);
59 | }
60 | LOG.error("Application failed to complete successfully");
61 | System.exit(2);
62 | }
63 |
64 | private void setupOpts(){
65 | opts = new Options();
66 | opts.addOption("appname", true, "Application Name. Default value - DistributedShell");
67 | opts.addOption("priority", true, "Application Priority. Default 0");
68 | opts.addOption("queue", true, "RM Queue in which this application is to be submitted");
69 | opts.addOption("timeout", true, "Application timeout in milliseconds");
70 | opts.addOption("master_memory", true, "Amount of memory in MB to be requested to run the application master");
71 | opts.addOption("master_vcores", true, "Amount of virtual cores to be requested to run the application master");
72 | opts.addOption("jar", true, "Jar file containing the application master");
73 |
74 | opts.addOption("log_properties", true, "log4j.properties file");
75 | opts.addOption("container_retry", true, "container retry count");
76 | opts.addOption("image", true, "docker image name");
77 |
78 | opts.addOption("debug", false, "Dump out debug information");
79 | opts.addOption("help", false, "Print usage");
80 | }
81 |
82 | /**
83 | * Parse command line options
84 | * @param args Parsed command line options
85 | * @return Whether the init was successful to run the client
86 | * @throws ParseException
87 | */
88 | public boolean init(String[] args) throws ParseException {
89 |
90 | CommandLine cliParser = new GnuParser().parse(opts, args, true);
91 |
92 | if (args.length == 0) {
93 | throw new IllegalArgumentException("No args specified for client to initialize");
94 | }
95 |
96 | if (cliParser.hasOption("log_properties")) {
97 | String log4jPath = cliParser.getOptionValue("log_properties");
98 | try {
99 | Log4jPropertyHelper.updateLog4jConfiguration(DockerClient.class, log4jPath);
100 | } catch (Exception e) {
101 | LOG.warn("Can not set up custom log4j properties. " + e);
102 | }
103 | }
104 |
105 | if (cliParser.hasOption("help")) {
106 | printUsage();
107 | return false;
108 | }
109 |
110 | if (cliParser.hasOption("debug")) {
111 | dockerClient.setDebugFlag(true);
112 | }
113 |
114 | appDescriptor.setAppName(cliParser.getOptionValue("appname", "DistributedShell"));
115 | appDescriptor.setAmPriority(Integer.parseInt(cliParser.getOptionValue("priority", "0")));
116 | appDescriptor.setAmQueue(cliParser.getOptionValue("queue", "default"));
117 |
118 | appDescriptor.setContainer_retry(Integer.parseInt(cliParser.getOptionValue("container_retry", "3")));
119 |
120 | appDescriptor.setClientTimeout(Integer.parseInt(cliParser.getOptionValue("timeout", "600000")));
121 |
122 | appDescriptor.setLog4jPropFile(cliParser.getOptionValue("log_properties", ""));
123 | appDescriptor.setAmJarPath(cliParser.getOptionValue("jar"));
124 |
125 | String dockerImage = cliParser.getOptionValue("image");
126 | checkNotEmpty(dockerImage, "No dockerImage given");
127 | appDescriptor.setDockerImage(dockerImage);
128 |
129 | String commandToRun = StringUtils.join(cliParser.getArgs(), " ");
130 | checkNotEmpty(commandToRun, "No command given");
131 |
132 | appDescriptor.setCommandToRun(commandToRun);
133 | return true;
134 | }
135 |
136 | private void printUsage() {
137 | new HelpFormatter().printHelp("[options] command [commandArgs]", opts);
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/java/com/sogou/dockeronyarn/client/model/SubmitException.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.client.model;
2 |
3 | /**
4 | * Created by guoshiwei on 14/11/28.
5 | */
6 | public class SubmitException extends RuntimeException{
7 | public SubmitException(String message){
8 | super(message);
9 | }
10 | public SubmitException(String message, Exception e){
11 | super(message, e);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/java/com/sogou/dockeronyarn/client/model/SubmitItem.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.client.model;
2 |
3 | import javax.xml.bind.annotation.XmlRootElement;
4 |
5 | @XmlRootElement
6 | public class SubmitItem {
7 | private String appname = "defaultApp";
8 | private String docker_image = null;
9 | private String workingdir = null;
10 | private String command = null;
11 | private long container_memory = 512;
12 | private long master_memory = 128;
13 | private long container_retry = 3;
14 | private int container_vcores = 1;
15 | private int priority = 10;
16 | private long timeout = 86400000;
17 | private String queue = "default";
18 | private String[] virualdirs = null;
19 | private boolean debug = false;
20 |
21 |
22 | public SubmitItem() {
23 | super();
24 | }
25 |
26 | public SubmitItem(String appname, String docker_image, String workingdir, String command, long container_memory, long master_memory, long container_retry, int container_vcores, int priority,
27 | long timeout, String queue, String[] virualdirs, boolean debug) {
28 | super();
29 | this.appname = appname;
30 | this.docker_image = docker_image;
31 | this.workingdir = workingdir;
32 | this.command = command;
33 | this.container_memory = container_memory;
34 | this.master_memory = master_memory;
35 | this.container_retry = container_retry;
36 | this.container_vcores = container_vcores;
37 | this.priority = priority;
38 | this.timeout = timeout;
39 | this.queue = queue;
40 | this.virualdirs = virualdirs;
41 | this.debug = debug;
42 | }
43 |
44 | public String[] getVirualdirs() {
45 | return virualdirs;
46 | }
47 |
48 | public void setVirualdirs(String[] virualdirs) {
49 | this.virualdirs = virualdirs;
50 | }
51 |
52 | public String getAppname() {
53 | return appname;
54 | }
55 |
56 | public void setAppname(String appname) {
57 | this.appname = appname;
58 | }
59 |
60 | public String getDocker_image() {
61 | return docker_image;
62 | }
63 |
64 | public void setDocker_image(String docker_image) {
65 | this.docker_image = docker_image;
66 | }
67 |
68 | public String getWorkingdir() {
69 | return workingdir;
70 | }
71 |
72 | public void setWorkingdir(String workingdir) {
73 | this.workingdir = workingdir;
74 | }
75 |
76 | public String getCommand() {
77 | return command;
78 | }
79 |
80 | public void setCommand(String command) {
81 | this.command = command;
82 | }
83 |
84 | public long getContainer_memory() {
85 | return container_memory;
86 | }
87 |
88 | public void setContainer_memory(long container_memory) {
89 | this.container_memory = container_memory;
90 | }
91 |
92 | public long getMaster_memory() {
93 | return master_memory;
94 | }
95 |
96 | public void setMaster_memory(long master_memory) {
97 | this.master_memory = master_memory;
98 | }
99 |
100 | public long getContainer_retry() {
101 | return container_retry;
102 | }
103 |
104 | public void setContainer_retry(long container_retry) {
105 | this.container_retry = container_retry;
106 | }
107 |
108 | public int getContainer_vcores() {
109 | return container_vcores;
110 | }
111 |
112 | public void setContainer_vcores(int container_vcores) {
113 | this.container_vcores = container_vcores;
114 | }
115 |
116 | public int getPriority() {
117 | return priority;
118 | }
119 |
120 | public void setPriority(int priority) {
121 | this.priority = priority;
122 | }
123 |
124 | public long getTimeout() {
125 | return timeout;
126 | }
127 |
128 | public void setTimeout(long timeout) {
129 | this.timeout = timeout;
130 | }
131 |
132 | public String getQueue() {
133 | return queue;
134 | }
135 |
136 | public void setQueue(String queue) {
137 | this.queue = queue;
138 | }
139 |
140 | public boolean isDebug() {
141 | return debug;
142 | }
143 |
144 | public void setDebug(boolean debug) {
145 | this.debug = debug;
146 | }
147 |
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/java/com/sogou/dockeronyarn/client/model/SubmitReturnItem.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.client.model;
2 |
3 | import org.apache.hadoop.yarn.api.records.ApplicationId;
4 |
5 | import javax.xml.bind.annotation.XmlRootElement;
6 |
7 | @XmlRootElement
8 | public class SubmitReturnItem {
9 | private String appid = null;
10 | private ApplicationId applicationIdObject;
11 |
12 | public ApplicationId getApplicationIdObject() {
13 | return applicationIdObject;
14 | }
15 |
16 | public void setApplicationIdObject(ApplicationId applicationIdObject) {
17 | this.applicationIdObject = applicationIdObject;
18 | }
19 |
20 | private String apptrackingurl = null;
21 | private int status = 0;
22 | private String message = null;
23 |
24 | public SubmitReturnItem() {
25 | super();
26 | }
27 |
28 | public SubmitReturnItem(String appid, String apptrackingurl, int status, String message) {
29 | super();
30 | this.appid = appid;
31 | this.apptrackingurl = apptrackingurl;
32 | this.status = status;
33 | this.message = message;
34 | }
35 |
36 | public String getMessage() {
37 | return message;
38 | }
39 |
40 | public void setMessage(String message) {
41 | this.message = message;
42 | }
43 |
44 | public String getAppid() {
45 | return appid;
46 | }
47 |
48 | public void setAppid(String appid) {
49 | this.appid = appid;
50 | }
51 |
52 | public String getApptrackingurl() {
53 | return apptrackingurl;
54 | }
55 |
56 | public void setApptrackingurl(String apptrackingurl) {
57 | this.apptrackingurl = apptrackingurl;
58 | }
59 |
60 | public int getStatus() {
61 | return status;
62 | }
63 |
64 | public void setStatus(int status) {
65 | this.status = status;
66 | }
67 |
68 |
69 |
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/resources/META-INF/services/javax.ws.rs.ext.RuntimeDelegate:
--------------------------------------------------------------------------------
1 | org.glassfish.jersey.internal.RuntimeDelegateImpl
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/resources/distributed-docker-site.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ddocker.runner.path
5 | /usr/lib/docker-on-yarn/runner.py
6 |
7 |
8 | ddocker.docker.cert.path
9 | /Users/guoshiwei/.boot2docker/certs/boot2docker-vm
10 |
11 |
12 | ddocker.docker.host
13 | unix:///var/run/docker.sock
14 |
15 |
16 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Define some default values that can be overridden by system properties
18 | hadoop.root.logger=INFO,console
19 | hadoop.log.dir=.
20 | hadoop.log.file=hadoop.log
21 |
22 | # Define the root logger to the system property "hadoop.root.logger".
23 | log4j.rootLogger=${hadoop.root.logger}, EventCounter
24 |
25 | # Logging Threshold
26 | log4j.threshold=ALL
27 |
28 | # Null Appender
29 | log4j.appender.NullAppender=org.apache.log4j.varia.NullAppender
30 |
31 | #
32 | # Rolling File Appender - cap space usage at 5gb.
33 | #
34 | hadoop.log.maxfilesize=256MB
35 | hadoop.log.maxbackupindex=20
36 | log4j.appender.RFA=org.apache.log4j.RollingFileAppender
37 | log4j.appender.RFA.File=${hadoop.log.dir}/${hadoop.log.file}
38 |
39 | log4j.appender.RFA.MaxFileSize=${hadoop.log.maxfilesize}
40 | log4j.appender.RFA.MaxBackupIndex=${hadoop.log.maxbackupindex}
41 |
42 | log4j.appender.RFA.layout=org.apache.log4j.PatternLayout
43 |
44 | # Pattern format: Date LogLevel LoggerName LogMessage
45 | log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
46 | # Debugging Pattern format
47 | #log4j.appender.RFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
48 |
49 |
50 | #
51 | # Daily Rolling File Appender
52 | #
53 |
54 | log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
55 | log4j.appender.DRFA.File=${hadoop.log.dir}/${hadoop.log.file}
56 |
57 | # Rollover at midnight
58 | log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
59 |
60 | log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
61 |
62 | # Pattern format: Date LogLevel LoggerName LogMessage
63 | log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
64 | # Debugging Pattern format
65 | #log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n
66 |
67 |
68 | #
69 | # console
70 | # Add "console" to rootlogger above if you want to use this
71 | #
72 |
73 | log4j.appender.console=org.apache.log4j.ConsoleAppender
74 | log4j.appender.console.target=System.err
75 | log4j.appender.console.layout=org.apache.log4j.PatternLayout
76 | log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n
77 |
78 | #
79 | # TaskLog Appender
80 | #
81 |
82 | #Default values
83 | hadoop.tasklog.taskid=null
84 | hadoop.tasklog.iscleanup=false
85 | hadoop.tasklog.noKeepSplits=4
86 | hadoop.tasklog.totalLogFileSize=100
87 | hadoop.tasklog.purgeLogSplits=true
88 | hadoop.tasklog.logsRetainHours=12
89 |
90 | log4j.appender.TLA=org.apache.hadoop.mapred.TaskLogAppender
91 | log4j.appender.TLA.taskId=${hadoop.tasklog.taskid}
92 | log4j.appender.TLA.isCleanup=${hadoop.tasklog.iscleanup}
93 | log4j.appender.TLA.totalLogFileSize=${hadoop.tasklog.totalLogFileSize}
94 |
95 | log4j.appender.TLA.layout=org.apache.log4j.PatternLayout
96 | log4j.appender.TLA.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
97 |
98 | #
99 | # HDFS block state change log from block manager
100 | #
101 | # Uncomment the following to suppress normal block state change
102 | # messages from BlockManager in NameNode.
103 | #log4j.logger.BlockStateChange=WARN
104 |
105 | #
106 | #Security appender
107 | #
108 | hadoop.security.logger=INFO,NullAppender
109 | hadoop.security.log.maxfilesize=256MB
110 | hadoop.security.log.maxbackupindex=20
111 | log4j.category.SecurityLogger=${hadoop.security.logger}
112 | hadoop.security.log.file=SecurityAuth-${user.name}.audit
113 | log4j.appender.RFAS=org.apache.log4j.RollingFileAppender
114 | log4j.appender.RFAS.File=${hadoop.log.dir}/${hadoop.security.log.file}
115 | log4j.appender.RFAS.layout=org.apache.log4j.PatternLayout
116 | log4j.appender.RFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
117 | log4j.appender.RFAS.MaxFileSize=${hadoop.security.log.maxfilesize}
118 | log4j.appender.RFAS.MaxBackupIndex=${hadoop.security.log.maxbackupindex}
119 |
120 | #
121 | # Daily Rolling Security appender
122 | #
123 | log4j.appender.DRFAS=org.apache.log4j.DailyRollingFileAppender
124 | log4j.appender.DRFAS.File=${hadoop.log.dir}/${hadoop.security.log.file}
125 | log4j.appender.DRFAS.layout=org.apache.log4j.PatternLayout
126 | log4j.appender.DRFAS.layout.ConversionPattern=%d{ISO8601} %p %c: %m%n
127 | log4j.appender.DRFAS.DatePattern=.yyyy-MM-dd
128 |
129 | #
130 | # hadoop configuration logging
131 | #
132 |
133 | # Uncomment the following line to turn off configuration deprecation warnings.
134 | # log4j.logger.org.apache.hadoop.conf.Configuration.deprecation=WARN
135 |
136 | #
137 | # hdfs audit logging
138 | #
139 | hdfs.audit.logger=INFO,NullAppender
140 | hdfs.audit.log.maxfilesize=256MB
141 | hdfs.audit.log.maxbackupindex=20
142 | log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=${hdfs.audit.logger}
143 | log4j.additivity.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=false
144 | log4j.appender.RFAAUDIT=org.apache.log4j.RollingFileAppender
145 | log4j.appender.RFAAUDIT.File=${hadoop.log.dir}/hdfs-audit.log
146 | log4j.appender.RFAAUDIT.layout=org.apache.log4j.PatternLayout
147 | log4j.appender.RFAAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
148 | log4j.appender.RFAAUDIT.MaxFileSize=${hdfs.audit.log.maxfilesize}
149 | log4j.appender.RFAAUDIT.MaxBackupIndex=${hdfs.audit.log.maxbackupindex}
150 |
151 | #
152 | # mapred audit logging
153 | #
154 | mapred.audit.logger=INFO,NullAppender
155 | mapred.audit.log.maxfilesize=256MB
156 | mapred.audit.log.maxbackupindex=20
157 | log4j.logger.org.apache.hadoop.mapred.AuditLogger=${mapred.audit.logger}
158 | log4j.additivity.org.apache.hadoop.mapred.AuditLogger=false
159 | log4j.appender.MRAUDIT=org.apache.log4j.RollingFileAppender
160 | log4j.appender.MRAUDIT.File=${hadoop.log.dir}/mapred-audit.log
161 | log4j.appender.MRAUDIT.layout=org.apache.log4j.PatternLayout
162 | log4j.appender.MRAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
163 | log4j.appender.MRAUDIT.MaxFileSize=${mapred.audit.log.maxfilesize}
164 | log4j.appender.MRAUDIT.MaxBackupIndex=${mapred.audit.log.maxbackupindex}
165 |
166 | # Custom Logging levels
167 |
168 | #log4j.logger.org.apache.hadoop.mapred.JobTracker=DEBUG
169 | #log4j.logger.org.apache.hadoop.mapred.TaskTracker=DEBUG
170 | #log4j.logger.org.apache.hadoop.hdfs.server.namenode.FSNamesystem.audit=DEBUG
171 |
172 | # Jets3t library
173 | log4j.logger.org.jets3t.service.impl.rest.httpclient.RestS3Service=ERROR
174 |
175 | # AWS SDK & S3A FileSystem
176 | log4j.logger.com.amazonaws=ERROR
177 | log4j.logger.com.amazonaws.http.AmazonHttpClient=ERROR
178 | log4j.logger.org.apache.hadoop.fs.s3a.S3AFileSystem=WARN
179 |
180 | #
181 | # Event Counter Appender
182 | # Sends counts of logging messages at different severity levels to Hadoop Metrics.
183 | #
184 | log4j.appender.EventCounter=org.apache.hadoop.log.metrics.EventCounter
185 |
186 | #
187 | # Job Summary Appender
188 | #
189 | # Use following logger to send summary to separate file defined by
190 | # hadoop.mapreduce.jobsummary.log.file :
191 | # hadoop.mapreduce.jobsummary.logger=INFO,JSA
192 | #
193 | hadoop.mapreduce.jobsummary.logger=${hadoop.root.logger}
194 | hadoop.mapreduce.jobsummary.log.file=hadoop-mapreduce.jobsummary.log
195 | hadoop.mapreduce.jobsummary.log.maxfilesize=256MB
196 | hadoop.mapreduce.jobsummary.log.maxbackupindex=20
197 | log4j.appender.JSA=org.apache.log4j.RollingFileAppender
198 | log4j.appender.JSA.File=${hadoop.log.dir}/${hadoop.mapreduce.jobsummary.log.file}
199 | log4j.appender.JSA.MaxFileSize=${hadoop.mapreduce.jobsummary.log.maxfilesize}
200 | log4j.appender.JSA.MaxBackupIndex=${hadoop.mapreduce.jobsummary.log.maxbackupindex}
201 | log4j.appender.JSA.layout=org.apache.log4j.PatternLayout
202 | log4j.appender.JSA.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n
203 | log4j.logger.org.apache.hadoop.mapred.JobInProgress$JobSummary=${hadoop.mapreduce.jobsummary.logger}
204 | log4j.additivity.org.apache.hadoop.mapred.JobInProgress$JobSummary=false
205 |
206 | #
207 | # Yarn ResourceManager Application Summary Log
208 | #
209 | # Set the ResourceManager summary log filename
210 | yarn.server.resourcemanager.appsummary.log.file=rm-appsummary.log
211 | # Set the ResourceManager summary log level and appender
212 | yarn.server.resourcemanager.appsummary.logger=${hadoop.root.logger}
213 | #yarn.server.resourcemanager.appsummary.logger=INFO,RMSUMMARY
214 |
215 | # To enable AppSummaryLogging for the RM,
216 | # set yarn.server.resourcemanager.appsummary.logger to
217 | # ,RMSUMMARY in hadoop-env.sh
218 |
219 | # Appender for ResourceManager Application Summary Log
220 | # Requires the following properties to be set
221 | # - hadoop.log.dir (Hadoop Log directory)
222 | # - yarn.server.resourcemanager.appsummary.log.file (resource manager app summary log filename)
223 | # - yarn.server.resourcemanager.appsummary.logger (resource manager app summary log level and appender)
224 |
225 | log4j.logger.org.apache.hadoop.yarn.server.resourcemanager.RMAppManager$ApplicationSummary=${yarn.server.resourcemanager.appsummary.logger}
226 | log4j.additivity.org.apache.hadoop.yarn.server.resourcemanager.RMAppManager$ApplicationSummary=false
227 | log4j.appender.RMSUMMARY=org.apache.log4j.RollingFileAppender
228 | log4j.appender.RMSUMMARY.File=${hadoop.log.dir}/${yarn.server.resourcemanager.appsummary.log.file}
229 | log4j.appender.RMSUMMARY.MaxFileSize=256MB
230 | log4j.appender.RMSUMMARY.MaxBackupIndex=20
231 | log4j.appender.RMSUMMARY.layout=org.apache.log4j.PatternLayout
232 | log4j.appender.RMSUMMARY.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
233 |
234 | # HS audit log configs
235 | #mapreduce.hs.audit.logger=INFO,HSAUDIT
236 | #log4j.logger.org.apache.hadoop.mapreduce.v2.hs.HSAuditLogger=${mapreduce.hs.audit.logger}
237 | #log4j.additivity.org.apache.hadoop.mapreduce.v2.hs.HSAuditLogger=false
238 | #log4j.appender.HSAUDIT=org.apache.log4j.DailyRollingFileAppender
239 | #log4j.appender.HSAUDIT.File=${hadoop.log.dir}/hs-audit.log
240 | #log4j.appender.HSAUDIT.layout=org.apache.log4j.PatternLayout
241 | #log4j.appender.HSAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
242 | #log4j.appender.HSAUDIT.DatePattern=.yyyy-MM-dd
243 |
244 | # Http Server Request Logs
245 | #log4j.logger.http.requests.namenode=INFO,namenoderequestlog
246 | #log4j.appender.namenoderequestlog=org.apache.hadoop.http.HttpRequestLogAppender
247 | #log4j.appender.namenoderequestlog.Filename=${hadoop.log.dir}/jetty-namenode-yyyy_mm_dd.log
248 | #log4j.appender.namenoderequestlog.RetainDays=3
249 |
250 | #log4j.logger.http.requests.datanode=INFO,datanoderequestlog
251 | #log4j.appender.datanoderequestlog=org.apache.hadoop.http.HttpRequestLogAppender
252 | #log4j.appender.datanoderequestlog.Filename=${hadoop.log.dir}/jetty-datanode-yyyy_mm_dd.log
253 | #log4j.appender.datanoderequestlog.RetainDays=3
254 |
255 | #log4j.logger.http.requests.resourcemanager=INFO,resourcemanagerrequestlog
256 | #log4j.appender.resourcemanagerrequestlog=org.apache.hadoop.http.HttpRequestLogAppender
257 | #log4j.appender.resourcemanagerrequestlog.Filename=${hadoop.log.dir}/jetty-resourcemanager-yyyy_mm_dd.log
258 | #log4j.appender.resourcemanagerrequestlog.RetainDays=3
259 |
260 | #log4j.logger.http.requests.jobhistory=INFO,jobhistoryrequestlog
261 | #log4j.appender.jobhistoryrequestlog=org.apache.hadoop.http.HttpRequestLogAppender
262 | #log4j.appender.jobhistoryrequestlog.Filename=${hadoop.log.dir}/jetty-jobhistory-yyyy_mm_dd.log
263 | #log4j.appender.jobhistoryrequestlog.RetainDays=3
264 |
265 | #log4j.logger.http.requests.nodemanager=INFO,nodemanagerrequestlog
266 | #log4j.appender.nodemanagerrequestlog=org.apache.hadoop.http.HttpRequestLogAppender
267 | #log4j.appender.nodemanagerrequestlog.Filename=${hadoop.log.dir}/jetty-nodemanager-yyyy_mm_dd.log
268 | #log4j.appender.nodemanagerrequestlog.RetainDays=3
269 |
--------------------------------------------------------------------------------
/distributed-docker-submit-client/test_docker_client.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | source ./hadoop-env.sh
3 | export HADOOP_CLASSPATH="/search/distributed-docker-submit-project/distributed-docker-appmaster/target/distributed-docker-appmaster-0.0.1-SNAPSHOT-jar-with-dependencies.jar"
4 | AM_JAR=../distributed-docker-appmaster/target/distributed-docker-appmaster-0.0.1-SNAPSHOT-jar-with-dependencies.jar
5 | CLIENT_JAR=target/distributed-docker-submit-client-0.0.1-SNAPSHOT.jar
6 | sh -x /usr/lib/hadoop/bin/hadoop jar $CLIENT_JAR com.sogou.dockeronyarn.client.DockerOnYarnClientCli \
7 | -jar $AM_JAR \
8 | -appname nimei \
9 | -queue root.hdfs \
10 | -image registry.docker.dev.sogou-inc.com:5000/clouddev/sogou-rhel-base:6.5 \
11 | echo hello world
12 |
13 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | distributed-docker-submit-server
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.m2e.core.maven2Builder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.m2e.core.maven2Nature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding/=UTF-8
3 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
5 | org.eclipse.jdt.core.compiler.source=1.6
6 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/assembly.xml:
--------------------------------------------------------------------------------
1 |
2 | bin
3 |
4 | tar.gz
5 | dir
6 |
7 |
8 |
9 | true
10 | lib
11 |
12 |
13 |
14 |
15 | /
16 |
17 | README.md
18 |
19 |
20 |
21 | bin
22 | /
23 |
24 |
25 | conf
26 | /conf
27 |
28 | *
29 |
30 |
31 |
32 | scripts
33 | /scripts
34 |
35 | *
36 | init.d/*
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/bin/monitor_docker_submit_server.sh:
--------------------------------------------------------------------------------
1 | flag=`jps -m | awk '{print "\$2"}' | grep -c '^DockerSubmitMain$'`
2 | if [ $flag = 0 ]
3 | then
4 | echo [`date`] Start docker submit server
5 | cd /search/eclipse/workspace/distributed-docker-submit-server/; sh start_server.sh
6 | fi
7 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/bin/start_server.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | project=docker-submit-server
3 | main_class=com.sogou.docker.server.DockerSubmitMain
4 |
5 | crontab=$(cat "/var/spool/cron/root" | grep "monitor_docker_submit_server" | wc -l)
6 | if [ $crontab -eq 0 ]
7 | then
8 | echo "*/1 * * * * cd /search/eclipse/distributed-docker-submit-server/; sh monitor_docker_submit_server.sh >> monitor.log 2>&1" >> /var/spool/cron/root
9 | fi
10 |
11 |
12 | running_num=`jps -ml | grep -c $main_class`
13 | if [ $running_num -ne 0 ]
14 | then
15 | echo "$project $main_class is already running..."
16 | exit 0
17 | fi
18 |
19 | dir='/search/eclipse/workspace/distributed-docker-submit-server/target'
20 | dir=`cd $dir/; pwd`
21 |
22 | bin_dir=$dir/bin
23 | lib_dir=$dir/lib
24 | conf_dir=$dir/conf
25 | log_dir=$dir/log
26 | cp *.properties target/
27 | cp target/*.jar target/lib/
28 | rm -fr $lib_dir/hadoop*
29 |
30 | JOBQUEUE_WORKER_HEAP_SIZE=128m
31 |
32 | for f in $lib_dir/*
33 | do
34 | CLASSPATH=$f:$CLASSPATH
35 | done
36 |
37 | CLASSPATH=$conf_dir:$CLASSPATH:`hadoop classpath`
38 |
39 | # set JVM heap size
40 | HEAP_SIZE=512m
41 | if [ "x${JOBQUEUE_WORKER_HEAP_SIZE}" != "x" ]
42 | then
43 | HEAP_SIZE=$JOBQUEUE_WORKER_HEAP_SIZE
44 | fi
45 | JAVA_OPTS="-Xmx${HEAP_SIZE}"
46 |
47 | # set jmx remote port
48 | JMX_REMOTE_OPTS=""
49 | JAVA_OPTS="$JAVA_OPTS $JMX_REMOTE_OPTS"
50 |
51 | cd $dir
52 | echo classpath: $CLASSPATH
53 | #nohup java $JAVA_OPTS -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=17891 -cp $CLASSPATH $main_class >$log_dir/$project.log 2>&1 &
54 | nohup java $JAVA_OPTS -cp $CLASSPATH $main_class >>submit.log &
55 | code=$?
56 | echo 'code: ' $code
57 | exit $code
58 |
59 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/bin/test.sh:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | curl -H "Accept: application/json" -H "Content-type: application/json" -X POST \
5 | -d '{"virualdir":"/search/working/", "docker_image":"10.134.69.187:5000/hadoop/cdh5client:1.2", "workingdir":"/search/sogouquery/", "command":"sh time_website.sh abcde 20141001"}' \
6 | http://127.0.0.1:18088/docker/submit
7 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/conf/log.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger= DEBUG, console ,file
2 | log4j.appender.file.layout=org.apache.log4j.PatternLayout
3 | log4j.appender.file=org.apache.log4j.RollingFileAppender
4 | log4j.appender.file.File=docker.log
5 | log4j.appender.file.MaxFileSize=30000KB
6 | log4j.appender.file.MaxBackupIndex=100
7 | #log4j.appender.file.DatePattern='.'yyyy-MM
8 | log4j.appender.file.layout.ConversionPattern= %-d{yyyy-MM-dd HH:mm:ss:SSS} [%p] (%t) %m%n
9 | log4j.logger.org.apache.zookeeper=ERROR,file
10 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/conf/server.properties:
--------------------------------------------------------------------------------
1 | server.ip=0.0.0.0
2 | server.port=18088
3 | dis.shell.jar=/search/eclipse/workspace/distributed-docker-submit-server/lib/distributed-docker-submit-client-0.0.1-SNAPSHOT.jar
--------------------------------------------------------------------------------
/distributed-docker-submit-server/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | distributed-docker-submit-server
5 | distributed-docker-submit-server
6 |
7 | distributed-docker-submit-project
8 | distributed-docker-submit-project
9 | 0.0.1-SNAPSHOT
10 | ../../distributed-docker-submit-project
11 |
12 |
13 | 0.0.1-SNAPSHOT
14 | distributed-docker-submit-server
15 | distributed-docker system of cloud_dev@sogou-inc.com
16 |
17 | true
18 |
19 | UTF-8
20 | true
21 | false
22 | 1.6
23 | 1.6
24 |
25 | 1.6.1
26 |
27 | 2.1.1
28 | 1.9
29 |
30 | 2.3.3
31 |
32 | 4.2.5
33 | 1.5
34 | 1.8
35 | 2.3
36 | 2.6
37 | 1.7.5
38 | 1.3.9
39 | 0.3
40 | 18.0
41 |
42 |
43 | 1.0.1
44 | 5.12.1
45 | 1.3
46 | 1.6
47 | 2.3.3
48 |
49 |
50 | 2.2
51 | 2.3.1
52 | 2.3.1
53 | 2.8.1
54 | 2.5.1
55 | 1.7
56 |
57 |
58 |
59 |
60 | my-local-repo
61 | file://${basedir}/lib/repo
62 |
63 |
64 | github-releases
65 | http://oss.sonatype.org/content/repositories/github-releases/
66 |
67 |
68 | clojars.org
69 | http://clojars.org/repo
70 |
71 |
72 | sogou.repo1
73 | http://cloud.sogou-inc.com/nexus/content/groups/public
74 | SogouRepository
75 |
76 |
77 |
78 |
79 |
80 | distributed-docker-submit-client
81 | distributed-docker-submit-client
82 | 0.0.1-SNAPSHOT
83 |
84 |
85 | commons-lang
86 | commons-lang
87 | ${commons-lang.version}
88 |
89 |
90 | commons-io
91 | commons-io
92 | ${commons-io.version}
93 |
94 |
95 | com.google.guava
96 | guava
97 | ${guava.version}
98 |
99 |
100 | org.apache.hadoop
101 | hadoop-yarn-common
102 | 2.5.0-cdh5.3.2
103 |
104 |
105 | jersey-core
106 | com.sun.jersey
107 |
108 |
109 |
110 |
111 |
112 | org.apache.hadoop
113 | hadoop-common
114 | 2.5.0-cdh5.3.2
115 |
116 |
117 | jersey-core
118 | com.sun.jersey
119 |
120 |
121 |
122 |
123 |
124 | org.apache.hadoop
125 | hadoop-yarn-client
126 | 2.5.0-cdh5.3.2
127 |
128 |
129 | jersey-core
130 | com.sun.jersey
131 |
132 |
133 |
134 |
135 | org.glassfish.jersey.containers
136 | jersey-container-servlet-core
137 | 2.0
138 |
139 |
140 |
141 | org.glassfish.jersey.media
142 | jersey-media-json-jackson
143 | 2.0
144 |
145 |
146 |
147 | javax.xml
148 | jaxb-api
149 | 2.1
150 |
151 |
152 |
153 |
154 | org.eclipse.jetty.aggregate
155 | jetty-all
156 | 8.0.4.v20111024
157 |
158 |
159 |
160 |
161 | org.eclipse.jetty
162 | jetty-webapp
163 | 8.0.4.v20111024
164 |
165 |
166 |
167 |
168 | org.glassfish.web
169 | javax.servlet.jsp
170 | 2.2.3
171 |
172 |
173 |
174 |
175 | org.glassfish.web
176 | javax.el
177 | 2.2.3
178 |
179 |
180 |
181 |
182 | org.glassfish.web
183 | javax.servlet.jsp.jstl
184 | 1.2.1
185 |
186 |
187 | jstl-api
188 | javax.servlet.jsp.jstl
189 |
190 |
191 |
192 |
193 |
194 | log4j
195 | log4j
196 | 1.2.17
197 |
198 |
199 | javax.mail
200 | mail
201 | 1.4.1
202 |
203 |
204 | org.apache.commons
205 | commons-exec
206 | 1.2
207 |
208 |
209 | commons-configuration
210 | commons-configuration
211 | 1.9
212 |
213 |
214 | com.sogou
215 | util.sendalert.javatool
216 | 0.0.4
217 |
218 |
219 |
220 | com.sun.jersey
221 | jersey-client
222 | 1.18.1
223 |
224 |
225 |
226 | junit
227 | junit
228 | 4.11
229 |
230 |
231 |
232 | org.mockito
233 | mockito-core
234 | 1.9.5
235 |
236 |
237 |
238 | commons-io
239 | commons-io
240 | 2.4
241 |
242 |
243 |
244 | com.sun.jersey
245 | jersey-server
246 | 1.17
247 |
248 |
249 | org.jboss.resteasy
250 | resteasy-jaxrs
251 | 2.3.3.Final
252 | provided
253 |
254 |
255 | com.sun.jersey
256 | jersey-grizzly2
257 | 1.17
258 |
259 |
260 | javax.ws.rs
261 | jsr311-api
262 | 1.1.1
263 |
264 |
265 | com.sun.jersey
266 | jersey-json
267 | 1.17
268 |
269 |
270 | com.sun.jersey
271 | jersey-client
272 | 1.17
273 |
274 |
275 | org.json
276 | json
277 | 20090211
278 |
279 |
280 |
281 | com.sun.jersey
282 | jersey-servlet
283 | 1.18.1
284 |
285 |
286 | org.jboss.resteasy
287 | resteasy-jaxrs
288 | 2.3.3.Final
289 | provided
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 | org.apache.maven.plugins
298 | maven-dependency-plugin
299 | 2.7
300 |
301 |
302 | copy-dependencies
303 | package
304 |
305 | copy-dependencies
306 |
307 |
308 | ${project.build.directory}/lib
309 | false
310 | false
311 | true
312 |
313 |
314 |
315 |
316 |
317 | org.apache.maven.plugins
318 | maven-surefire-plugin
319 | 2.17
320 |
321 |
322 | ${project.build.directory}/conf
323 |
324 |
325 |
326 |
327 | maven-compiler-plugin
328 | 3.0
329 |
330 | 1.6
331 | 1.6
332 | GB18030
333 |
334 |
335 |
336 | org.apache.maven.plugins
337 | maven-assembly-plugin
338 |
339 |
340 | assembly.xml
341 |
342 |
343 |
344 |
345 | make-assembly
346 | package
347 |
348 | single
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 | org.apache.maven.plugins
357 | maven-jar-plugin
358 | 2.4
359 |
360 |
361 |
362 | true
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 | org.eclipse.m2e
373 | lifecycle-mapping
374 | 1.0.0
375 |
376 |
377 |
378 |
379 |
380 |
381 | org.apache.maven.plugins
382 |
383 |
384 | maven-dependency-plugin
385 |
386 |
387 | [2.7,)
388 |
389 |
390 |
391 | copy-dependencies
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/src/main/java/com/sogou/dockeronyarn/server/DockerServer.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.server;
2 |
3 | import java.io.IOException;
4 | import java.net.URI;
5 |
6 | import javax.ws.rs.core.UriBuilder;
7 |
8 | import org.eclipse.jetty.server.handler.StatisticsHandler;
9 | import org.glassfish.grizzly.http.server.HttpServer;
10 |
11 | import com.sogou.dockeronyarn.util.StaticData;
12 | import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
13 | import com.sun.jersey.api.core.PackagesResourceConfig;
14 | import com.sun.jersey.api.core.ResourceConfig;
15 |
16 | public class DockerServer {
17 |
18 | public static String HTTP_CONTEXT = "/";
19 | private static StatisticsHandler STATIC = null;
20 |
21 | private static URI BASE_URI = UriBuilder
22 | .fromUri(String.format("http://%s/", StaticData.SERVER_IP))
23 | .port(StaticData.SERVER_PORT).build();
24 |
25 |
26 | public void startHttpService() throws Exception {
27 |
28 | try {
29 | ResourceConfig rc = new PackagesResourceConfig("com.sogou.docker.service");
30 | HttpServer httpServer = GrizzlyServerFactory.createHttpServer(
31 | BASE_URI, rc);
32 | httpServer.start();
33 |
34 | } catch (IOException e) {
35 | e.printStackTrace();
36 | }
37 | }
38 |
39 | public static StatisticsHandler getStaticHandler() {
40 | return STATIC;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/src/main/java/com/sogou/dockeronyarn/server/DockerSubmitMain.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.server;
2 |
3 | import org.apache.commons.lang.math.RandomUtils;
4 |
5 |
6 | public class DockerSubmitMain {
7 |
8 | private static Object lock = new Object();
9 |
10 | public static void main(String[] args) throws Exception {
11 | Thread.currentThread().setName("Main" + RandomUtils.nextInt());
12 | Runtime.getRuntime().addShutdownHook(new ShutdownHook());
13 | try {
14 | DockerServer server = new DockerServer();
15 | server.startHttpService();
16 |
17 | synchronized(lock){
18 | lock.wait();
19 | }
20 |
21 |
22 | } catch (Exception e) {
23 | System.exit(0);
24 | }
25 | }
26 |
27 | public static class ShutdownHook extends Thread{
28 | public void run(){
29 | try{
30 | lock.notifyAll();
31 | }catch(IllegalMonitorStateException e){
32 |
33 | }
34 |
35 | }
36 | }
37 |
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/src/main/java/com/sogou/dockeronyarn/service/DockerService.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.service;
2 |
3 | import javax.ws.rs.Consumes;
4 | import javax.ws.rs.GET;
5 | import javax.ws.rs.POST;
6 | import javax.ws.rs.Path;
7 | import javax.ws.rs.Produces;
8 | import javax.ws.rs.QueryParam;
9 | import javax.ws.rs.core.MediaType;
10 | import javax.ws.rs.core.Response;
11 | import javax.ws.rs.core.Response.Status;
12 |
13 | import com.sogou.dockeronyarn.client.DockerApplicationSubmitter;
14 | import com.sogou.dockeronyarn.client.model.SubmitException;
15 | import com.sogou.dockeronyarn.util.StaticData;
16 | import org.apache.commons.logging.Log;
17 | import org.apache.commons.logging.LogFactory;
18 |
19 | import com.sogou.dockeronyarn.client.model.SubmitItem;
20 | import com.sogou.dockeronyarn.client.model.SubmitReturnItem;
21 |
22 | @Path("/docker")
23 | public class DockerService {
24 | private static final Log logger = LogFactory.getLog(DockerService.class);
25 |
26 | @POST
27 | @Path("submit")
28 | @Consumes(MediaType.APPLICATION_JSON)
29 | @Produces(MediaType.APPLICATION_JSON)
30 | public Response submit(SubmitItem si) {
31 | logger.debug("submit service start");
32 | Status status = Status.NO_CONTENT;
33 | String message = null;
34 | SubmitReturnItem sri = null;
35 | try{
36 | sri = new DockerApplicationSubmitter(StaticData.DIS_SHELL_JAR).submitToYarn(si);
37 | status = Status.OK;
38 | message = sri.getMessage();
39 | }catch(SubmitException e){
40 | message = e.getMessage();
41 | status = Status.NO_CONTENT;
42 | }
43 |
44 | logger.debug(message);
45 |
46 | return Response.status(status).header("Message", message).entity(sri).build();
47 | }
48 |
49 | @GET
50 | @Path("test")
51 | @Consumes(MediaType.APPLICATION_JSON)
52 | @Produces(MediaType.APPLICATION_JSON)
53 | public Response test(@QueryParam("str") String str) {
54 | logger.debug("test service start");
55 | Status status = Status.NO_CONTENT;
56 | String message = null;
57 |
58 |
59 | status = Status.OK;
60 | message = "submit succeed";
61 |
62 | logger.debug(message);
63 |
64 | return Response.status(status).header("Message", message).entity(str).build();
65 | }
66 |
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/src/main/java/com/sogou/dockeronyarn/util/LogUtil.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.util;
2 |
3 | import java.util.concurrent.ConcurrentSkipListMap;
4 | import org.apache.log4j.Logger;
5 | import com.sogou.util.sendalert.bean.AlertLevel;
6 | import com.sogou.util.sendalert.bean.AlertType;
7 |
8 |
9 | public class LogUtil {
10 | private static Logger logger = Logger.getLogger(LogUtil.class);
11 | private static ConcurrentSkipListMap exceptions = new ConcurrentSkipListMap();
12 | //private static AlertSenderThread alertSender = null;
13 |
14 | // static {
15 | // alertSender = new AlertSenderThread();
16 | // alertSender.start();
17 | // }
18 |
19 | public static void debug(String info) {
20 | logger.debug(info);
21 | }
22 |
23 | public static void debug(Object ...infos) {
24 | if (!logger.isDebugEnabled()) {
25 | return ;
26 | }
27 | logger.debug(objsToString(infos));
28 | }
29 |
30 | public static void log(String info) {
31 | logger.info(info);
32 | }
33 |
34 | public static void log(Object ...infos) {
35 | if (!logger.isInfoEnabled()) {
36 | return ;
37 | }
38 | logger.info(objsToString(infos));
39 | }
40 |
41 | public static void warn(String info) {
42 | logger.warn(info);
43 | }
44 |
45 | public static void warn(Object ...infos) {
46 | String logInfo = objsToString(infos);
47 | logger.warn(logInfo);
48 | }
49 |
50 | private static String objsToString(Object ...infos) {
51 | StringBuilder logInfo = new StringBuilder();
52 | for (Object info : infos) {
53 | if (info == null) {
54 | logInfo.append("null");
55 | } else {
56 | logInfo.append(info.toString());
57 | }
58 | logInfo.append(' ');
59 | }
60 | return logInfo.toString();
61 | }
62 |
63 | public static void error(String info) {
64 | logger.error(info);
65 | }
66 |
67 | public static void fatal(String info) {
68 | logger.fatal(info);
69 | }
70 |
71 | public static void error(Exception e) {
72 | exceptions.put(System.currentTimeMillis(), e);
73 | if (exceptions.size() > 20) {
74 | exceptions.remove(exceptions.firstKey());
75 | }
76 | logger.error("Exception:", e);
77 | }
78 |
79 | public static void error(String info, Exception e) {
80 | exceptions.put(System.currentTimeMillis(), e);
81 | if (exceptions.size() > 20) {
82 | exceptions.remove(exceptions.firstKey());
83 | }
84 | logger.error(info, e);
85 | }
86 |
87 | public static ConcurrentSkipListMap getExceptions() {
88 | return exceptions;
89 | }
90 |
91 | public static void setExceptions(ConcurrentSkipListMap exceptions) {
92 | LogUtil.exceptions = exceptions;
93 | }
94 |
95 | public static void warnAndSendAlert(String title, Object ...infos) {
96 | String logInfo = objsToString(infos);
97 | logger.warn(logInfo);
98 | }
99 |
100 | private static void sendAlert(String title, String logInfo, AlertType type, AlertLevel level) {
101 | //alertSender.addAlertInfo(new AlertInfo(title, logInfo, type, level));
102 | }
103 |
104 | public static void errorAndSendAlert(String title, Object ...infos) {
105 | String logInfo = objsToString(infos);
106 | logger.warn(logInfo);
107 | }
108 |
109 | public static void sendNormalAlert(String title, String info) {
110 | // sendAlert(title, info, AlertType.DAILY, AlertLevel.NORMAL);
111 | }
112 |
113 | public static void fatal(Exception e) {
114 | logger.fatal(e);
115 | e.printStackTrace();
116 | }
117 |
118 | public static void error(Object ...infos) {
119 | String logInfo = objsToString(infos);
120 | logger.error(logInfo);
121 | }
122 |
123 | }
124 |
125 | class AlertInfo {
126 |
127 | String title = null;
128 | String logInfo = null;
129 | AlertType type = null;
130 | AlertLevel level = null;
131 |
132 | public AlertInfo(String title, String logInfo, AlertType type,
133 | AlertLevel level) {
134 | super();
135 | this.title = title;
136 | this.logInfo = logInfo;
137 | this.type = type;
138 | this.level = level;
139 | }
140 |
141 | }
142 |
143 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/src/main/java/com/sogou/dockeronyarn/util/PropertyManager.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.util;
2 |
3 | import org.apache.commons.configuration.Configuration;
4 | import org.apache.commons.configuration.ConfigurationException;
5 | import org.apache.commons.configuration.PropertiesConfiguration;
6 |
7 | public class PropertyManager {
8 | private String propertyFile;
9 | private Configuration config;
10 |
11 | public PropertyManager(String propertyFile) {
12 | this.propertyFile = propertyFile;
13 | try {
14 | config = new PropertiesConfiguration(PropertyManager.class
15 | .getClassLoader().getResource(propertyFile));
16 | } catch (ConfigurationException e) {
17 | e.printStackTrace();
18 | System.exit(1);
19 | }
20 | }
21 |
22 | public String getProperty(String key) {
23 | if (config.containsKey(key)) {
24 | return config.getString(key);
25 | } else {
26 | return null;
27 | }
28 | }
29 |
30 | public String getPropertyFile() {
31 | return propertyFile;
32 | }
33 |
34 | public void setPropertyFile(String propertyFile) {
35 | this.propertyFile = propertyFile;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/distributed-docker-submit-server/src/main/java/com/sogou/dockeronyarn/util/StaticData.java:
--------------------------------------------------------------------------------
1 | package com.sogou.dockeronyarn.util;
2 |
3 | import org.apache.log4j.Logger;
4 | import org.apache.log4j.PropertyConfigurator;
5 |
6 | public class StaticData {
7 | public static String LOG4J_CONFIG = "conf/log.properties";
8 | private static PropertyManager serverPropertyManager = new PropertyManager(
9 | "server.properties");
10 |
11 | /* server info */
12 | public static String SERVER_IP = serverPropertyManager
13 | .getProperty("server.ip");
14 | public static int SERVER_PORT = Integer.parseInt(serverPropertyManager
15 | .getProperty("server.port"));
16 |
17 | public static String DIS_SHELL_JAR = serverPropertyManager
18 | .getProperty("dis.shell.jar");
19 |
20 |
21 |
22 |
23 |
24 | public static Logger getLogger(Class clazz) {
25 | PropertyConfigurator.configure(clazz.getClassLoader().getResource(
26 | StaticData.LOG4J_CONFIG));
27 | return Logger.getLogger(clazz.getName());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | distributed-docker-submit-project
6 | distributed-docker-submit-project
7 |
8 |
9 | 0.0.1-SNAPSHOT
10 | distributed-docker-submit-project
11 | distributed-docker system of cloud_dev@sogou-inc.com
12 |
13 | pom
14 |
15 |
16 | distributed-docker-submit-server
17 | distributed-docker-submit-client
18 | distributed-docker-appmaster
19 |
20 |
21 |
22 | sogou.repo1
23 | http://cloud.sogou-inc.com/nexus/content/groups/public
24 | SogouRepository
25 |
26 |
27 |
28 |
29 |
30 | maven-deploy-plugin
31 |
32 | true
33 |
34 |
35 |
36 | org.apache.rat
37 | apache-rat-plugin
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------