HBASE-8345 Add all available resources in RootResource and VersionResource to rest RemoteAdmin (Aleksandr Shulman)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1476025 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
jxiang 2013-04-26 02:18:08 +00:00
parent 1eadb508ab
commit f6c6992581
2 changed files with 310 additions and 42 deletions

View File

@ -19,15 +19,24 @@
package org.apache.hadoop.hbase.rest.client; package org.apache.hadoop.hbase.rest.client;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.rest.Constants; import org.apache.hadoop.hbase.rest.Constants;
import org.apache.hadoop.hbase.rest.model.StorageClusterStatusModel;
import org.apache.hadoop.hbase.rest.model.StorageClusterVersionModel;
import org.apache.hadoop.hbase.rest.model.TableListModel;
import org.apache.hadoop.hbase.rest.model.TableSchemaModel; import org.apache.hadoop.hbase.rest.model.TableSchemaModel;
import org.apache.hadoop.hbase.rest.model.VersionModel;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
@InterfaceAudience.Public @InterfaceAudience.Public
@ -40,8 +49,14 @@ public class RemoteAdmin {
final int maxRetries; final int maxRetries;
final long sleepTime; final long sleepTime;
// This unmarshaller is necessary for getting the /version/cluster resource.
// This resource does not support protobufs. Therefore this is necessary to
// request/interpret it as XML.
private static volatile Unmarshaller versionClusterUnmarshaller;
/** /**
* Constructor * Constructor
*
* @param client * @param client
* @param conf * @param conf
*/ */
@ -49,6 +64,16 @@ public class RemoteAdmin {
this(client, conf, null); this(client, conf, null);
} }
static Unmarshaller getUnmarsheller() throws JAXBException {
if (versionClusterUnmarshaller == null) {
RemoteAdmin.versionClusterUnmarshaller = JAXBContext.newInstance(
StorageClusterVersionModel.class).createUnmarshaller();
}
return RemoteAdmin.versionClusterUnmarshaller;
}
/** /**
* Constructor * Constructor
* @param client * @param client
@ -72,24 +97,156 @@ public class RemoteAdmin {
return isTableAvailable(Bytes.toBytes(tableName)); return isTableAvailable(Bytes.toBytes(tableName));
} }
/**
* @return string representing the rest api's version
* @throws IOEXception
* if the endpoint does not exist, there is a timeout, or some other
* general failure mode
*/
public VersionModel getRestVersion() throws IOException {
StringBuilder path = new StringBuilder();
path.append('/');
if (accessToken != null) {
path.append(accessToken);
path.append('/');
}
path.append("version/rest");
int code = 0;
for (int i = 0; i < maxRetries; i++) {
Response response = client.get(path.toString(),
Constants.MIMETYPE_PROTOBUF);
code = response.getCode();
switch (code) {
case 200:
VersionModel v = new VersionModel();
return (VersionModel) v.getObjectFromMessage(response.getBody());
case 404:
throw new IOException("REST version not found");
case 509:
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
break;
default:
throw new IOException("get request to " + path.toString()
+ " returned " + code);
}
}
throw new IOException("get request to " + path.toString() + " timed out");
}
/**
* @return string representing the cluster's version
* @throws IOEXception if the endpoint does not exist, there is a timeout, or some other general failure mode
*/
public StorageClusterStatusModel getClusterStatus() throws IOException {
StringBuilder path = new StringBuilder();
path.append('/');
if (accessToken !=null) {
path.append(accessToken);
path.append('/');
}
path.append("status/cluster");
int code = 0;
for (int i = 0; i < maxRetries; i++) {
Response response = client.get(path.toString(),
Constants.MIMETYPE_PROTOBUF);
code = response.getCode();
switch (code) {
case 200:
StorageClusterStatusModel s = new StorageClusterStatusModel();
return (StorageClusterStatusModel) s.getObjectFromMessage(response
.getBody());
case 404:
throw new IOException("Cluster version not found");
case 509:
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
break;
default:
throw new IOException("get request to " + path + " returned " + code);
}
}
throw new IOException("get request to " + path + " timed out");
}
/**
* @return string representing the cluster's version
* @throws IOEXception
* if the endpoint does not exist, there is a timeout, or some other
* general failure mode
*/
public StorageClusterVersionModel getClusterVersion() throws IOException {
StringBuilder path = new StringBuilder();
path.append('/');
if (accessToken != null) {
path.append(accessToken);
path.append('/');
}
path.append("version/cluster");
int code = 0;
for (int i = 0; i < maxRetries; i++) {
Response response = client.get(path.toString(), Constants.MIMETYPE_XML);
code = response.getCode();
switch (code) {
case 200:
try {
return (StorageClusterVersionModel) getUnmarsheller().unmarshal(
new ByteArrayInputStream(response.getBody()));
} catch (JAXBException jaxbe) {
throw new IOException(
"Issue parsing StorageClusterVersionModel object in XML form: "
+ jaxbe.getLocalizedMessage());
}
case 404:
throw new IOException("Cluster version not found");
case 509:
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
break;
default:
throw new IOException(path.toString() + " request returned " + code);
}
}
throw new IOException("get request to " + path.toString()
+ " request timed out");
}
/** /**
* @param tableName name of table to check * @param tableName name of table to check
* @return true if all regions of the table are available * @return true if all regions of the table are available
* @throws IOException if a remote or network exception occurs * @throws IOException if a remote or network exception occurs
*/ */
public boolean isTableAvailable(byte[] tableName) throws IOException { public boolean isTableAvailable(byte[] tableName) throws IOException {
StringBuilder sb = new StringBuilder(); StringBuilder path = new StringBuilder();
sb.append('/'); path.append('/');
if (accessToken != null) { if (accessToken != null) {
sb.append(accessToken); path.append(accessToken);
sb.append('/'); path.append('/');
} }
sb.append(Bytes.toStringBinary(tableName)); path.append(Bytes.toStringBinary(tableName));
sb.append('/'); path.append('/');
sb.append("exists"); path.append("exists");
int code = 0; int code = 0;
for (int i = 0; i < maxRetries; i++) { for (int i = 0; i < maxRetries; i++) {
Response response = client.get(sb.toString()); Response response = client.get(path.toString(), Constants.MIMETYPE_PROTOBUF);
code = response.getCode(); code = response.getCode();
switch (code) { switch (code) {
case 200: case 200:
@ -102,10 +259,10 @@ public class RemoteAdmin {
} catch (InterruptedException e) { } } catch (InterruptedException e) { }
break; break;
default: default:
throw new IOException("exists request returned " + code); throw new IOException("get request to " + path.toString() + " returned " + code);
} }
} }
throw new IOException("exists request timed out"); throw new IOException("get request to " + path.toString() + " timed out");
} }
/** /**
@ -116,18 +273,18 @@ public class RemoteAdmin {
public void createTable(HTableDescriptor desc) public void createTable(HTableDescriptor desc)
throws IOException { throws IOException {
TableSchemaModel model = new TableSchemaModel(desc); TableSchemaModel model = new TableSchemaModel(desc);
StringBuilder sb = new StringBuilder(); StringBuilder path = new StringBuilder();
sb.append('/'); path.append('/');
if (accessToken != null) { if (accessToken != null) {
sb.append(accessToken); path.append(accessToken);
sb.append('/'); path.append('/');
} }
sb.append(Bytes.toStringBinary(desc.getName())); path.append(Bytes.toStringBinary(desc.getName()));
sb.append('/'); path.append('/');
sb.append("schema"); path.append("schema");
int code = 0; int code = 0;
for (int i = 0; i < maxRetries; i++) { for (int i = 0; i < maxRetries; i++) {
Response response = client.put(sb.toString(), Constants.MIMETYPE_PROTOBUF, Response response = client.put(path.toString(), Constants.MIMETYPE_PROTOBUF,
model.createProtobufOutput()); model.createProtobufOutput());
code = response.getCode(); code = response.getCode();
switch (code) { switch (code) {
@ -139,10 +296,10 @@ public class RemoteAdmin {
} catch (InterruptedException e) { } } catch (InterruptedException e) { }
break; break;
default: default:
throw new IOException("create request returned " + code); throw new IOException("create request to " + path.toString() + " returned " + code);
} }
} }
throw new IOException("create request timed out"); throw new IOException("create request to " + path.toString() + " timed out");
} }
/** /**
@ -160,18 +317,18 @@ public class RemoteAdmin {
* @throws IOException if a remote or network exception occurs * @throws IOException if a remote or network exception occurs
*/ */
public void deleteTable(final byte [] tableName) throws IOException { public void deleteTable(final byte [] tableName) throws IOException {
StringBuilder sb = new StringBuilder(); StringBuilder path = new StringBuilder();
sb.append('/'); path.append('/');
if (accessToken != null) { if (accessToken != null) {
sb.append(accessToken); path.append(accessToken);
sb.append('/'); path.append('/');
} }
sb.append(Bytes.toStringBinary(tableName)); path.append(Bytes.toStringBinary(tableName));
sb.append('/'); path.append('/');
sb.append("schema"); path.append("schema");
int code = 0; int code = 0;
for (int i = 0; i < maxRetries; i++) { for (int i = 0; i < maxRetries; i++) {
Response response = client.delete(sb.toString()); Response response = client.delete(path.toString());
code = response.getCode(); code = response.getCode();
switch (code) { switch (code) {
case 200: case 200:
@ -182,10 +339,52 @@ public class RemoteAdmin {
} catch (InterruptedException e) { } } catch (InterruptedException e) { }
break; break;
default: default:
throw new IOException("delete request returned " + code); throw new IOException("delete request to " + path.toString() + " returned " + code);
} }
} }
throw new IOException("delete request timed out"); throw new IOException("delete request to " + path.toString() + " timed out");
} }
/**
* @return string representing the cluster's version
* @throws IOEXception
* if the endpoint does not exist, there is a timeout, or some other
* general failure mode
*/
public TableListModel getTableList() throws IOException {
StringBuilder path = new StringBuilder();
path.append('/');
if (accessToken != null) {
path.append(accessToken);
path.append('/');
}
int code = 0;
for (int i = 0; i < maxRetries; i++) {
// Response response = client.get(path.toString(),
// Constants.MIMETYPE_XML);
Response response = client.get(path.toString(),
Constants.MIMETYPE_PROTOBUF);
code = response.getCode();
switch (code) {
case 200:
TableListModel t = new TableListModel();
return (TableListModel) t.getObjectFromMessage(response.getBody());
case 404:
throw new IOException("Table list not found");
case 509:
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
break;
default:
throw new IOException("get request to " + path.toString()
+ " request returned " + code);
}
}
throw new IOException("get request to " + path.toString()
+ " request timed out");
}
} }

View File

@ -19,13 +19,22 @@
package org.apache.hadoop.hbase.rest.client; package org.apache.hadoop.hbase.rest.client;
import org.apache.hadoop.hbase.*; import static org.junit.Assert.assertEquals;
import org.apache.hadoop.hbase.client.HBaseAdmin; import static org.junit.Assert.assertFalse;
import org.apache.hadoop.hbase.rest.HBaseRESTTestingUtility; import static org.junit.Assert.assertTrue;
import org.apache.hadoop.hbase.rest.client.Client;
import org.apache.hadoop.hbase.util.Bytes;
import static org.junit.Assert.*; import java.util.List;
import org.apache.hadoop.hbase.ClusterStatus;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MediumTests;
import org.apache.hadoop.hbase.rest.HBaseRESTTestingUtility;
import org.apache.hadoop.hbase.rest.model.StorageClusterStatusModel;
import org.apache.hadoop.hbase.rest.model.TableModel;
import org.apache.hadoop.hbase.rest.model.VersionModel;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -33,13 +42,15 @@ import org.junit.experimental.categories.Category;
@Category(MediumTests.class) @Category(MediumTests.class)
public class TestRemoteAdmin { public class TestRemoteAdmin {
private static final String TABLE_1 = "TestRemoteAdmin_Table_1";
private static final byte[] COLUMN_1 = Bytes.toBytes("a");
static final HTableDescriptor DESC_1 = new HTableDescriptor(TABLE_1);
private static final HBaseTestingUtility TEST_UTIL = private static final HBaseTestingUtility TEST_UTIL =
new HBaseTestingUtility(); new HBaseTestingUtility();
private static final HBaseRESTTestingUtility REST_TEST_UTIL = private static final HBaseRESTTestingUtility REST_TEST_UTIL =
new HBaseRESTTestingUtility(); new HBaseRESTTestingUtility();
private static final String TABLE_1 = "TestRemoteAdmin_Table_1";
private static final String TABLE_2 = TABLE_1 + System.currentTimeMillis();
private static final byte[] COLUMN_1 = Bytes.toBytes("a");
static final HTableDescriptor DESC_1 = new HTableDescriptor(TABLE_1);
static final HTableDescriptor DESC_2 = new HTableDescriptor(TABLE_2);
private static RemoteAdmin remoteAdmin; private static RemoteAdmin remoteAdmin;
@BeforeClass @BeforeClass
@ -69,5 +80,63 @@ public class TestRemoteAdmin {
assertFalse(remoteAdmin.isTableAvailable(TABLE_1)); assertFalse(remoteAdmin.isTableAvailable(TABLE_1));
} }
@Test
public void testGetRestVersion() throws Exception {
VersionModel RETURNED_REST_VERSION = remoteAdmin.getRestVersion();
System.out.print("Returned version is: " + RETURNED_REST_VERSION);
// Assert that it contains info about rest version, OS, JVM
assertTrue("Returned REST version did not contain info about rest.",
RETURNED_REST_VERSION.toString().contains("rest"));
assertTrue("Returned REST version did not contain info about the JVM.",
RETURNED_REST_VERSION.toString().contains("JVM"));
assertTrue("Returned REST version did not contain info about OS.",
RETURNED_REST_VERSION.toString().contains("OS"));
} }
@Test
public void testClusterVersion() throws Exception {
// testing the /version/cluster endpoint
final String HBASE_VERSION = TEST_UTIL.getHBaseCluster().getClusterStatus()
.getHBaseVersion();
assertEquals("Cluster status from REST API did not match. ", HBASE_VERSION,
remoteAdmin.getClusterVersion().getVersion());
}
@Test
public void testClusterStatus() throws Exception {
ClusterStatus status = TEST_UTIL.getHBaseClusterInterface()
.getClusterStatus();
StorageClusterStatusModel returnedStatus = remoteAdmin.getClusterStatus();
assertEquals(
"Region count from cluster status and returned status did not match up. ",
status.getRegionsCount(), returnedStatus.getRegions());
assertEquals(
"Dead server count from cluster status and returned status did not match up. ",
status.getDeadServers(), returnedStatus.getDeadNodes().size());
assertEquals(
"Number of requests from cluster status and returned status did not match up. ",
status.getRequestsCount(), returnedStatus.getRequests());
}
@Test
public void testListTables() throws Exception {
remoteAdmin.createTable(DESC_2);
List<TableModel> tableList = remoteAdmin.getTableList().getTables();
System.out.println("List of tables is: ");
boolean found = false;
for (TableModel tm : tableList) {
if (tm.getName().equals(TABLE_2)) {
found = true;
break;
}
}
assertTrue("Table " + TABLE_2 + " was not found by get request to '/'",
found);
}
}