1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.Map;
24
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.hadoop.classification.InterfaceAudience;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.hbase.HBaseClusterManager.CommandProvider.Operation;
29 import org.apache.hadoop.hbase.util.Pair;
30 import org.apache.hadoop.util.Shell;
31
32
33
34
35
36
37
38
39 @InterfaceAudience.Private
40 public class HBaseClusterManager extends ClusterManager {
41 private String sshUserName;
42 private String sshOptions;
43
44
45
46
47
48 private static final String DEFAULT_TUNNEL_CMD = "/usr/bin/ssh %1$s %2$s%3$s%4$s \"%5$s\"";
49 private String tunnelCmd;
50
51 @Override
52 public void setConf(Configuration conf) {
53 super.setConf(conf);
54 if (conf == null) {
55
56 return;
57 }
58 sshUserName = conf.get("hbase.it.clustermanager.ssh.user", "");
59 String extraSshOptions = conf.get("hbase.it.clustermanager.ssh.opts", "");
60 sshOptions = System.getenv("HBASE_SSH_OPTS");
61 if (!extraSshOptions.isEmpty()) {
62 sshOptions = StringUtils.join(new Object[] { sshOptions, extraSshOptions }, " ");
63 }
64 sshOptions = (sshOptions == null) ? "" : sshOptions;
65 tunnelCmd = conf.get("hbase.it.clustermanager.ssh.cmd", DEFAULT_TUNNEL_CMD);
66
67 if ((sshUserName != null && sshUserName.length() > 0) ||
68 (sshOptions != null && sshOptions.length() > 0)) {
69 LOG.info("Running with SSH user [" + sshUserName + "] and options [" + sshOptions + "]");
70 }
71 }
72
73
74
75
76 protected class RemoteShell extends Shell.ShellCommandExecutor {
77 private String hostname;
78
79 public RemoteShell(String hostname, String[] execString, File dir, Map<String, String> env,
80 long timeout) {
81 super(execString, dir, env, timeout);
82 this.hostname = hostname;
83 }
84
85 public RemoteShell(String hostname, String[] execString, File dir, Map<String, String> env) {
86 super(execString, dir, env);
87 this.hostname = hostname;
88 }
89
90 public RemoteShell(String hostname, String[] execString, File dir) {
91 super(execString, dir);
92 this.hostname = hostname;
93 }
94
95 public RemoteShell(String hostname, String[] execString) {
96 super(execString);
97 this.hostname = hostname;
98 }
99
100 @Override
101 public String[] getExecString() {
102 String at = sshUserName.isEmpty() ? "" : "@";
103 String remoteCmd = StringUtils.join(super.getExecString(), " ");
104 String cmd = String.format(tunnelCmd, sshOptions, sshUserName, at, hostname, remoteCmd);
105 LOG.info("Executing full command [" + cmd + "]");
106 return new String[] { "/usr/bin/env", "bash", "-c", cmd };
107 }
108
109 @Override
110 public void execute() throws IOException {
111 super.execute();
112 }
113 }
114
115
116
117
118
119
120 static abstract class CommandProvider {
121
122 enum Operation {
123 START, STOP, RESTART
124 }
125
126 public abstract String getCommand(ServiceType service, Operation op);
127
128 public String isRunningCommand(ServiceType service) {
129 return findPidCommand(service);
130 }
131
132 protected String findPidCommand(ServiceType service) {
133 return String.format("ps aux | grep proc_%s | grep -v grep | tr -s ' ' | cut -d ' ' -f2",
134 service);
135 }
136
137 public String signalCommand(ServiceType service, String signal) {
138 return String.format("%s | xargs kill -s %s", findPidCommand(service), signal);
139 }
140 }
141
142
143
144
145 static class HBaseShellCommandProvider extends CommandProvider {
146 private final String hbaseHome;
147 private final String confDir;
148
149 HBaseShellCommandProvider(Configuration conf) {
150 hbaseHome = conf.get("hbase.it.clustermanager.hbase.home",
151 System.getenv("HBASE_HOME"));
152 String tmp = conf.get("hbase.it.clustermanager.hbase.conf.dir",
153 System.getenv("HBASE_CONF_DIR"));
154 if (tmp != null) {
155 confDir = String.format("--config %s", tmp);
156 } else {
157 confDir = "";
158 }
159 }
160
161 @Override
162 public String getCommand(ServiceType service, Operation op) {
163 return String.format("%s/bin/hbase-daemon.sh %s %s %s", hbaseHome, confDir,
164 op.toString().toLowerCase(), service);
165 }
166 }
167
168 public HBaseClusterManager() {
169 super();
170 }
171
172 protected CommandProvider getCommandProvider(ServiceType service) {
173
174
175 return new HBaseShellCommandProvider(getConf());
176 }
177
178
179
180
181
182
183 private Pair<Integer, String> exec(String hostname, String... cmd) throws IOException {
184 LOG.info("Executing remote command: " + StringUtils.join(cmd, " ") + " , hostname:" + hostname);
185
186 RemoteShell shell = new RemoteShell(hostname, cmd);
187 shell.execute();
188
189 LOG.info("Executed remote command, exit code:" + shell.getExitCode()
190 + " , output:" + shell.getOutput());
191
192 return new Pair<Integer, String>(shell.getExitCode(), shell.getOutput());
193 }
194
195 private void exec(String hostname, ServiceType service, Operation op) throws IOException {
196 exec(hostname, getCommandProvider(service).getCommand(service, op));
197 }
198
199 @Override
200 public void start(ServiceType service, String hostname) throws IOException {
201 exec(hostname, service, Operation.START);
202 }
203
204 @Override
205 public void stop(ServiceType service, String hostname) throws IOException {
206 exec(hostname, service, Operation.STOP);
207 }
208
209 @Override
210 public void restart(ServiceType service, String hostname) throws IOException {
211 exec(hostname, service, Operation.RESTART);
212 }
213
214 @Override
215 public void signal(ServiceType service, String signal, String hostname) throws IOException {
216 exec(hostname, getCommandProvider(service).signalCommand(service, signal));
217 }
218
219 @Override
220 public boolean isRunning(ServiceType service, String hostname) throws IOException {
221 String ret = exec(hostname, getCommandProvider(service).isRunningCommand(service))
222 .getSecond();
223 return ret.length() > 0;
224 }
225
226 }