1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.rest.client;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.IOException;
24 import java.io.InterruptedIOException;
25
26 import javax.xml.bind.JAXBContext;
27 import javax.xml.bind.JAXBException;
28 import javax.xml.bind.Unmarshaller;
29 import javax.xml.stream.XMLInputFactory;
30 import javax.xml.stream.XMLStreamException;
31 import javax.xml.stream.XMLStreamReader;
32
33 import org.apache.hadoop.hbase.classification.InterfaceAudience;
34 import org.apache.hadoop.hbase.classification.InterfaceStability;
35 import org.apache.hadoop.conf.Configuration;
36
37 import org.apache.hadoop.hbase.HTableDescriptor;
38 import org.apache.hadoop.hbase.rest.Constants;
39 import org.apache.hadoop.hbase.rest.model.StorageClusterStatusModel;
40 import org.apache.hadoop.hbase.rest.model.StorageClusterVersionModel;
41 import org.apache.hadoop.hbase.rest.model.TableListModel;
42 import org.apache.hadoop.hbase.rest.model.TableSchemaModel;
43 import org.apache.hadoop.hbase.rest.model.VersionModel;
44 import org.apache.hadoop.hbase.util.Bytes;
45
46 @InterfaceAudience.Public
47 @InterfaceStability.Stable
48 public class RemoteAdmin {
49
50 final Client client;
51 final Configuration conf;
52 final String accessToken;
53 final int maxRetries;
54 final long sleepTime;
55
56
57
58
59 private static volatile Unmarshaller versionClusterUnmarshaller;
60
61
62
63
64
65
66
67 public RemoteAdmin(Client client, Configuration conf) {
68 this(client, conf, null);
69 }
70
71 static Unmarshaller getUnmarsheller() throws JAXBException {
72
73 if (versionClusterUnmarshaller == null) {
74
75 RemoteAdmin.versionClusterUnmarshaller = JAXBContext.newInstance(
76 StorageClusterVersionModel.class).createUnmarshaller();
77 }
78 return RemoteAdmin.versionClusterUnmarshaller;
79 }
80
81
82
83
84
85
86
87 public RemoteAdmin(Client client, Configuration conf, String accessToken) {
88 this.client = client;
89 this.conf = conf;
90 this.accessToken = accessToken;
91 this.maxRetries = conf.getInt("hbase.rest.client.max.retries", 10);
92 this.sleepTime = conf.getLong("hbase.rest.client.sleep", 1000);
93 }
94
95
96
97
98
99
100 public boolean isTableAvailable(String tableName) throws IOException {
101 return isTableAvailable(Bytes.toBytes(tableName));
102 }
103
104
105
106
107
108
109
110 public VersionModel getRestVersion() throws IOException {
111
112 StringBuilder path = new StringBuilder();
113 path.append('/');
114 if (accessToken != null) {
115 path.append(accessToken);
116 path.append('/');
117 }
118
119 path.append("version/rest");
120
121 int code = 0;
122 for (int i = 0; i < maxRetries; i++) {
123 Response response = client.get(path.toString(),
124 Constants.MIMETYPE_PROTOBUF);
125 code = response.getCode();
126 switch (code) {
127 case 200:
128
129 VersionModel v = new VersionModel();
130 return (VersionModel) v.getObjectFromMessage(response.getBody());
131 case 404:
132 throw new IOException("REST version not found");
133 case 509:
134 try {
135 Thread.sleep(sleepTime);
136 } catch (InterruptedException e) {
137 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
138 }
139 break;
140 default:
141 throw new IOException("get request to " + path.toString()
142 + " returned " + code);
143 }
144 }
145 throw new IOException("get request to " + path.toString() + " timed out");
146 }
147
148
149
150
151
152 public StorageClusterStatusModel getClusterStatus() throws IOException {
153
154 StringBuilder path = new StringBuilder();
155 path.append('/');
156 if (accessToken !=null) {
157 path.append(accessToken);
158 path.append('/');
159 }
160
161 path.append("status/cluster");
162
163 int code = 0;
164 for (int i = 0; i < maxRetries; i++) {
165 Response response = client.get(path.toString(),
166 Constants.MIMETYPE_PROTOBUF);
167 code = response.getCode();
168 switch (code) {
169 case 200:
170 StorageClusterStatusModel s = new StorageClusterStatusModel();
171 return (StorageClusterStatusModel) s.getObjectFromMessage(response
172 .getBody());
173 case 404:
174 throw new IOException("Cluster version not found");
175 case 509:
176 try {
177 Thread.sleep(sleepTime);
178 } catch (InterruptedException e) {
179 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
180 }
181 break;
182 default:
183 throw new IOException("get request to " + path + " returned " + code);
184 }
185 }
186 throw new IOException("get request to " + path + " timed out");
187 }
188
189
190
191
192
193
194
195 public StorageClusterVersionModel getClusterVersion() throws IOException {
196
197 StringBuilder path = new StringBuilder();
198 path.append('/');
199 if (accessToken != null) {
200 path.append(accessToken);
201 path.append('/');
202 }
203
204 path.append("version/cluster");
205
206 int code = 0;
207 for (int i = 0; i < maxRetries; i++) {
208 Response response = client.get(path.toString(), Constants.MIMETYPE_XML);
209 code = response.getCode();
210 switch (code) {
211 case 200:
212 try {
213
214 return (StorageClusterVersionModel) getUnmarsheller().unmarshal(
215 getInputStream(response));
216 } catch (JAXBException jaxbe) {
217
218 throw new IOException(
219 "Issue parsing StorageClusterVersionModel object in XML form: "
220 + jaxbe.getLocalizedMessage(), jaxbe);
221 }
222 case 404:
223 throw new IOException("Cluster version not found");
224 case 509:
225 try {
226 Thread.sleep(sleepTime);
227 } catch (InterruptedException e) {
228 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
229 }
230 break;
231 default:
232 throw new IOException(path.toString() + " request returned " + code);
233 }
234 }
235 throw new IOException("get request to " + path.toString()
236 + " request timed out");
237 }
238
239
240
241
242
243
244 public boolean isTableAvailable(byte[] tableName) throws IOException {
245 StringBuilder path = new StringBuilder();
246 path.append('/');
247 if (accessToken != null) {
248 path.append(accessToken);
249 path.append('/');
250 }
251 path.append(Bytes.toStringBinary(tableName));
252 path.append('/');
253 path.append("exists");
254 int code = 0;
255 for (int i = 0; i < maxRetries; i++) {
256 Response response = client.get(path.toString(), Constants.MIMETYPE_PROTOBUF);
257 code = response.getCode();
258 switch (code) {
259 case 200:
260 return true;
261 case 404:
262 return false;
263 case 509:
264 try {
265 Thread.sleep(sleepTime);
266 } catch (InterruptedException e) {
267 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
268 }
269 break;
270 default:
271 throw new IOException("get request to " + path.toString() + " returned " + code);
272 }
273 }
274 throw new IOException("get request to " + path.toString() + " timed out");
275 }
276
277
278
279
280
281
282 public void createTable(HTableDescriptor desc)
283 throws IOException {
284 TableSchemaModel model = new TableSchemaModel(desc);
285 StringBuilder path = new StringBuilder();
286 path.append('/');
287 if (accessToken != null) {
288 path.append(accessToken);
289 path.append('/');
290 }
291 path.append(desc.getTableName());
292 path.append('/');
293 path.append("schema");
294 int code = 0;
295 for (int i = 0; i < maxRetries; i++) {
296 Response response = client.put(path.toString(), Constants.MIMETYPE_PROTOBUF,
297 model.createProtobufOutput());
298 code = response.getCode();
299 switch (code) {
300 case 201:
301 return;
302 case 509:
303 try {
304 Thread.sleep(sleepTime);
305 } catch (InterruptedException e) {
306 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
307 }
308 break;
309 default:
310 throw new IOException("create request to " + path.toString() + " returned " + code);
311 }
312 }
313 throw new IOException("create request to " + path.toString() + " timed out");
314 }
315
316
317
318
319
320
321 public void deleteTable(final String tableName) throws IOException {
322 deleteTable(Bytes.toBytes(tableName));
323 }
324
325
326
327
328
329
330 public void deleteTable(final byte [] tableName) throws IOException {
331 StringBuilder path = new StringBuilder();
332 path.append('/');
333 if (accessToken != null) {
334 path.append(accessToken);
335 path.append('/');
336 }
337 path.append(Bytes.toStringBinary(tableName));
338 path.append('/');
339 path.append("schema");
340 int code = 0;
341 for (int i = 0; i < maxRetries; i++) {
342 Response response = client.delete(path.toString());
343 code = response.getCode();
344 switch (code) {
345 case 200:
346 return;
347 case 509:
348 try {
349 Thread.sleep(sleepTime);
350 } catch (InterruptedException e) {
351 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
352 }
353 break;
354 default:
355 throw new IOException("delete request to " + path.toString() + " returned " + code);
356 }
357 }
358 throw new IOException("delete request to " + path.toString() + " timed out");
359 }
360
361
362
363
364
365
366
367 public TableListModel getTableList() throws IOException {
368
369 StringBuilder path = new StringBuilder();
370 path.append('/');
371 if (accessToken != null) {
372 path.append(accessToken);
373 path.append('/');
374 }
375
376 int code = 0;
377 for (int i = 0; i < maxRetries; i++) {
378
379
380 Response response = client.get(path.toString(),
381 Constants.MIMETYPE_PROTOBUF);
382 code = response.getCode();
383 switch (code) {
384 case 200:
385 TableListModel t = new TableListModel();
386 return (TableListModel) t.getObjectFromMessage(response.getBody());
387 case 404:
388 throw new IOException("Table list not found");
389 case 509:
390 try {
391 Thread.sleep(sleepTime);
392 } catch (InterruptedException e) {
393 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
394 }
395 break;
396 default:
397 throw new IOException("get request to " + path.toString()
398 + " request returned " + code);
399 }
400 }
401 throw new IOException("get request to " + path.toString()
402 + " request timed out");
403 }
404
405
406
407
408
409
410
411
412 private XMLStreamReader getInputStream(Response response) throws IOException {
413 try {
414
415 XMLInputFactory xif = XMLInputFactory.newFactory();
416 xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
417 xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
418 return xif.createXMLStreamReader(new ByteArrayInputStream(response.getBody()));
419 } catch (XMLStreamException e) {
420 throw new IOException("Failed to parse XML", e);
421 }
422 }
423 }