blob: 86315e97303fe36dd39180b4345eb24ed0aeb5a3 [file] [log] [blame]
Thomas Vachuskaf9c84362015-04-15 11:20:45 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onlab.stc;
17
Thomas Vachuska86439372015-06-05 09:21:32 -070018import org.onlab.stc.Coordinator.Status;
19
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070020import java.io.BufferedReader;
21import java.io.File;
22import java.io.IOException;
23import java.io.InputStream;
24import java.io.InputStreamReader;
25import java.io.PrintWriter;
26
Thomas Vachuska4bfccd542015-05-30 00:35:25 -070027import static java.lang.String.format;
Thomas Vachuska86439372015-06-05 09:21:32 -070028import static org.onlab.stc.Coordinator.Status.FAILED;
29import static org.onlab.stc.Coordinator.Status.SUCCEEDED;
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070030import static org.onlab.stc.Coordinator.print;
31
32/**
33 * Manages execution of the specified step or a group.
34 */
35class StepProcessor implements Runnable {
36
Thomas Vachuska86439372015-06-05 09:21:32 -070037 private static final String IGNORE_CODE = "~";
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070038 private static final int FAIL = -1;
39
40 static String launcher = "stc-launcher ";
41
42 private final Step step;
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070043 private final File logDir;
44
45 private Process process;
46 private StepProcessListener delegate;
47
48 /**
49 * Creates a process monitor.
50 *
51 * @param step step or group to be executed
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070052 * @param logDir directory where step process log should be stored
53 * @param delegate process lifecycle listener
54 */
Thomas Vachuska86439372015-06-05 09:21:32 -070055 StepProcessor(Step step, File logDir, StepProcessListener delegate) {
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070056 this.step = step;
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070057 this.logDir = logDir;
58 this.delegate = delegate;
59 }
60
61 @Override
62 public void run() {
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070063 delegate.onStart(step);
Thomas Vachuska86439372015-06-05 09:21:32 -070064 int code = execute();
65 boolean ignoreCode = step.env() != null && step.env.equals(IGNORE_CODE);
66 Status status = ignoreCode || code == 0 ? SUCCEEDED : FAILED;
67 delegate.onCompletion(step, status);
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070068 }
69
70 /**
71 * Executes the step process.
72 *
73 * @return exit code
74 */
75 private int execute() {
Thomas Vachuska4bfccd542015-05-30 00:35:25 -070076 try (PrintWriter pw = new PrintWriter(logFile())) {
77 process = Runtime.getRuntime().exec(command());
Thomas Vachuskaf9c84362015-04-15 11:20:45 -070078 processOutput(pw);
79
80 // Wait for the process to complete and get its exit code.
81 if (process.isAlive()) {
82 process.waitFor();
83 }
84 return process.exitValue();
85
86 } catch (IOException e) {
87 print("Unable to run step %s using command %s", step.name(), step.command());
88 } catch (InterruptedException e) {
89 print("Step %s interrupted", step.name());
90 }
91 return FAIL;
92 }
93
94 /**
Thomas Vachuska4bfccd542015-05-30 00:35:25 -070095 * Returns ready-to-run command for the step.
96 *
97 * @return command to execute
98 */
99 private String command() {
100 return format("%s %s %s %s", launcher,
101 step.env() != null ? step.env() : "-",
102 step.cwd() != null ? step.cwd() : "-",
103 step.command());
104 }
105
106 /**
Thomas Vachuskaf9c84362015-04-15 11:20:45 -0700107 * Captures output of the step process.
108 *
109 * @param pw print writer to send output to
110 * @throws IOException if unable to read output or write logs
111 */
112 private void processOutput(PrintWriter pw) throws IOException {
113 InputStream out = process.getInputStream();
114 BufferedReader br = new BufferedReader(new InputStreamReader(out));
115
116 // Slurp its combined stderr/stdout
117 String line;
118 while ((line = br.readLine()) != null) {
119 pw.println(line);
120 delegate.onOutput(step, line);
121 }
122 }
123
124 /**
Thomas Vachuska4bfccd542015-05-30 00:35:25 -0700125 * Returns the log file for the step output.
Thomas Vachuskaf9c84362015-04-15 11:20:45 -0700126 *
Thomas Vachuskaf9c84362015-04-15 11:20:45 -0700127 * @return log file
128 */
Thomas Vachuska4bfccd542015-05-30 00:35:25 -0700129 private File logFile() {
Thomas Vachuskaf9c84362015-04-15 11:20:45 -0700130 return new File(logDir, step.name() + ".log");
131 }
132
133}