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 LOG.info("Running with SSH user [" + sshUserName + "] and options [" + sshOptions + "]");
67 }
68
69
70
71
72 protected class RemoteShell extends Shell.ShellCommandExecutor {
73 private String hostname;
74
75 public RemoteShell(String hostname, String[] execString, File dir, Map<String, String> env,
76 long timeout) {
77 super(execString, dir, env, timeout);
78 this.hostname = hostname;
79 }
80
81 public RemoteShell(String hostname, String[] execString, File dir, Map<String, String> env) {
82 super(execString, dir, env);
83 this.hostname = hostname;
84 }
85
86 public RemoteShell(String hostname, String[] execString, File dir) {
87 super(execString, dir);
88 this.hostname = hostname;
89 }
90
91 public RemoteShell(String hostname, String[] execString) {
92 super(execString);
93 this.hostname = hostname;
94 }
95
96 public String[] getExecString() {
97 String at = sshUserName.isEmpty() ? "" : "@";
98 String remoteCmd = StringUtils.join(super.getExecString(), " ");
99 String cmd = String.format(tunnelCmd, sshOptions, sshUserName, at, hostname, remoteCmd);
100 LOG.info("Executing full command [" + cmd + "]");
101 return new String[] { "/usr/bin/env", "bash", "-c", cmd };
102 }
103
104 @Override
105 public void execute() throws IOException {
106 super.execute();
107 }
108 }
109
110
111
112
113
114
115 static abstract class CommandProvider {
116
117 enum Operation {
118 START, STOP, RESTART
119 }
120
121 public abstract String getCommand(ServiceType service, Operation op);
122
123 public String isRunningCommand(ServiceType service) {
124 return findPidCommand(service);
125 }
126
127 protected String findPidCommand(ServiceType service) {
128 String servicePathFilter = "";
129 if (service == ServiceType.HBASE_MASTER || service == ServiceType.HBASE_REGIONSERVER) {
130 servicePathFilter = " | grep hbase";
131 }
132 return String.format("ps ux | grep %s %s | grep -v grep | tr -s ' ' | cut -d ' ' -f2",
133 service, servicePathFilter);
134 }
135
136 public String signalCommand(ServiceType service, String signal) {
137 return String.format("%s | xargs kill -s %s", findPidCommand(service), signal);
138 }
139 }
140
141
142
143
144 static class HBaseShellCommandProvider extends CommandProvider {
145 private String getHBaseHome() {
146 return System.getenv("HBASE_HOME");
147 }
148
149 private String getConfig() {
150 String confDir = System.getenv("HBASE_CONF_DIR");
151 if (confDir != null) {
152 return String.format("--config %s", confDir);
153 }
154 return "";
155 }
156
157 @Override
158 public String getCommand(ServiceType service, Operation op) {
159 return String.format("%s/bin/hbase-daemon.sh %s %s %s", getHBaseHome(), getConfig(),
160 op.toString().toLowerCase(), service);
161 }
162 }
163
164 public HBaseClusterManager() {
165 super();
166 }
167
168 protected CommandProvider getCommandProvider(ServiceType service) {
169
170
171 return new HBaseShellCommandProvider();
172 }
173
174
175
176
177
178
179 private Pair<Integer, String> exec(String hostname, String... cmd) throws IOException {
180 LOG.info("Executing remote command: " + StringUtils.join(cmd, " ") + " , hostname:" + hostname);
181
182 RemoteShell shell = new RemoteShell(hostname, cmd);
183 shell.execute();
184
185 LOG.info("Executed remote command, exit code:" + shell.getExitCode()
186 + " , output:" + shell.getOutput());
187
188 return new Pair<Integer, String>(shell.getExitCode(), shell.getOutput());
189 }
190
191 private void exec(String hostname, ServiceType service, Operation op) throws IOException {
192 exec(hostname, getCommandProvider(service).getCommand(service, op));
193 }
194
195 @Override
196 public void start(ServiceType service, String hostname) throws IOException {
197 exec(hostname, service, Operation.START);
198 }
199
200 @Override
201 public void stop(ServiceType service, String hostname) throws IOException {
202 exec(hostname, service, Operation.STOP);
203 }
204
205 @Override
206 public void restart(ServiceType service, String hostname) throws IOException {
207 exec(hostname, service, Operation.RESTART);
208 }
209
210 @Override
211 public void signal(ServiceType service, String signal, String hostname) throws IOException {
212 exec(hostname, getCommandProvider(service).signalCommand(service, signal));
213 }
214
215 @Override
216 public boolean isRunning(ServiceType service, String hostname) throws IOException {
217 String ret = exec(hostname, getCommandProvider(service).isRunningCommand(service))
218 .getSecond();
219 return ret.length() > 0;
220 }
221
222 }