Return-Path: X-Original-To: apmail-helix-commits-archive@minotaur.apache.org Delivered-To: apmail-helix-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8C591D946 for ; Wed, 24 Oct 2012 23:17:28 +0000 (UTC) Received: (qmail 77897 invoked by uid 500); 24 Oct 2012 23:17:28 -0000 Delivered-To: apmail-helix-commits-archive@helix.apache.org Received: (qmail 77876 invoked by uid 500); 24 Oct 2012 23:17:28 -0000 Mailing-List: contact commits-help@helix.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@helix.incubator.apache.org Delivered-To: mailing list commits@helix.incubator.apache.org Received: (qmail 77866 invoked by uid 99); 24 Oct 2012 23:17:28 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 Oct 2012 23:17:28 +0000 X-ASF-Spam-Status: No, hits=-2000.7 required=5.0 tests=ALL_TRUSTED,RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Wed, 24 Oct 2012 23:15:20 +0000 Received: (qmail 72810 invoked by uid 99); 24 Oct 2012 23:14:57 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 Oct 2012 23:14:57 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 9E9164F234; Wed, 24 Oct 2012 23:14:57 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: kishoreg@apache.org To: commits@helix.incubator.apache.org X-Mailer: ASF-Git Admin Mailer Subject: [3/42] Refactoring the package names and removing jsql parser Message-Id: <20121024231457.9E9164F234@tyr.zones.apache.org> Date: Wed, 24 Oct 2012 23:14:57 +0000 (UTC) X-Virus-Checked: Checked by ClamAV on apache.org http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StateModelsResource.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StateModelsResource.java b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StateModelsResource.java new file mode 100644 index 0000000..1ec7e09 --- /dev/null +++ b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StateModelsResource.java @@ -0,0 +1,150 @@ +/** + * Copyright (C) 2012 LinkedIn Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.helix.webapp.resources; + +import java.io.IOException; +import java.util.List; + +import org.apache.helix.HelixDataAccessor; +import org.apache.helix.HelixException; +import org.apache.helix.ZNRecord; +import org.apache.helix.manager.zk.ZkClient; +import org.apache.helix.model.StateModelDefinition; +import org.apache.helix.tools.ClusterSetup; +import org.apache.helix.webapp.RestAdminApplication; +import org.apache.log4j.Logger; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.map.JsonMappingException; +import org.restlet.Context; +import org.restlet.data.MediaType; +import org.restlet.data.Request; +import org.restlet.data.Response; +import org.restlet.data.Status; +import org.restlet.resource.Representation; +import org.restlet.resource.Resource; +import org.restlet.resource.StringRepresentation; +import org.restlet.resource.Variant; + + +public class StateModelsResource extends Resource +{ + private final static Logger LOG = Logger.getLogger(StateModelsResource.class); + + public StateModelsResource(Context context, + Request request, + Response response) + { + super(context, request, response); + getVariants().add(new Variant(MediaType.TEXT_PLAIN)); + getVariants().add(new Variant(MediaType.APPLICATION_JSON)); + } + + @Override + public boolean allowGet() + { + return true; + } + + @Override + public boolean allowPost() + { + return true; + } + + @Override + public boolean allowPut() + { + return false; + } + + @Override + public boolean allowDelete() + { + return false; + } + + @Override + public Representation represent(Variant variant) + { + StringRepresentation presentation = null; + try + { + presentation = getStateModelsRepresentation(); + } + + catch(Exception e) + { + String error = ClusterRepresentationUtil.getErrorAsJsonStringFromException(e); + presentation = new StringRepresentation(error, MediaType.APPLICATION_JSON); + + LOG.error("", e); + } + return presentation; + } + + StringRepresentation getStateModelsRepresentation() throws JsonGenerationException, JsonMappingException, IOException + { + String clusterName = (String)getRequest().getAttributes().get("clusterName"); + ZkClient zkClient = (ZkClient)getContext().getAttributes().get(RestAdminApplication.ZKCLIENT); + ClusterSetup setupTool = new ClusterSetup(zkClient); + + List models = setupTool.getClusterManagementTool().getStateModelDefs(clusterName); + + ZNRecord modelDefinitions = new ZNRecord("modelDefinitions"); + modelDefinitions.setListField("models", models); + + StringRepresentation representation = new StringRepresentation(ClusterRepresentationUtil.ZNRecordToJson(modelDefinitions), MediaType.APPLICATION_JSON); + + return representation; + } + + @Override + public void acceptRepresentation(Representation entity) + { + try + { + String clusterName = (String)getRequest().getAttributes().get("clusterName"); + ZkClient zkClient = (ZkClient)getContext().getAttributes().get(RestAdminApplication.ZKCLIENT);; + + JsonParameters jsonParameters = new JsonParameters(entity); + String command = jsonParameters.getCommand(); + + + if(command.equalsIgnoreCase(ClusterSetup.addStateModelDef)) + { + ZNRecord newStateModel = jsonParameters.getExtraParameter(JsonParameters.NEW_STATE_MODEL_DEF); + HelixDataAccessor accessor = ClusterRepresentationUtil.getClusterDataAccessor(zkClient, clusterName); + + accessor.setProperty(accessor.keyBuilder().stateModelDef(newStateModel.getId()), new StateModelDefinition(newStateModel) ); + getResponse().setEntity(getStateModelsRepresentation()); + } + else + { + throw new HelixException("Unsupported command: " + command + + ". Should be one of [" + ClusterSetup.addStateModelDef + "]"); + } + + getResponse().setStatus(Status.SUCCESS_OK); + } + catch(Exception e) + { + getResponse().setEntity(ClusterRepresentationUtil.getErrorAsJsonStringFromException(e), + MediaType.APPLICATION_JSON); + getResponse().setStatus(Status.SUCCESS_OK); + LOG.error("Error in posting " + entity, e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StatusUpdateResource.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StatusUpdateResource.java b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StatusUpdateResource.java new file mode 100644 index 0000000..a105e75 --- /dev/null +++ b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StatusUpdateResource.java @@ -0,0 +1,127 @@ +/** + * Copyright (C) 2012 LinkedIn Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.helix.webapp.resources; + +import java.io.IOException; + +import org.apache.helix.PropertyKey; +import org.apache.helix.PropertyKey.Builder; +import org.apache.helix.manager.zk.ZkClient; +import org.apache.helix.webapp.RestAdminApplication; +import org.apache.log4j.Logger; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.map.JsonMappingException; +import org.restlet.Context; +import org.restlet.data.MediaType; +import org.restlet.data.Request; +import org.restlet.data.Response; +import org.restlet.resource.Representation; +import org.restlet.resource.Resource; +import org.restlet.resource.StringRepresentation; +import org.restlet.resource.Variant; + + +public class StatusUpdateResource extends Resource +{ + private final static Logger LOG = Logger.getLogger(StatusUpdateResource.class); + + public StatusUpdateResource(Context context, Request request, Response response) + { + super(context, request, response); + getVariants().add(new Variant(MediaType.TEXT_PLAIN)); + getVariants().add(new Variant(MediaType.APPLICATION_JSON)); + } + + @Override + public boolean allowGet() + { + return true; + } + + @Override + public boolean allowPost() + { + return false; + } + + @Override + public boolean allowPut() + { + return false; + } + + @Override + public boolean allowDelete() + { + return false; + } + + @Override + public Representation represent(Variant variant) + { + StringRepresentation presentation = null; + try + { + String clusterName = (String) getRequest().getAttributes().get("clusterName"); + String instanceName = (String) getRequest().getAttributes().get("instanceName"); + String resourceGroup = (String) getRequest().getAttributes().get("resourceName"); + + presentation = + getInstanceStatusUpdateRepresentation( + clusterName, + instanceName, + resourceGroup); + } + catch (Exception e) + { + String error = ClusterRepresentationUtil.getErrorAsJsonStringFromException(e); + presentation = new StringRepresentation(error, MediaType.APPLICATION_JSON); + + LOG.error("", e); + } + return presentation; + } + + StringRepresentation getInstanceStatusUpdateRepresentation( + String clusterName, + String instanceName, + String resourceGroup) throws JsonGenerationException, + JsonMappingException, + IOException + { + ZkClient zkClient = (ZkClient)getContext().getAttributes().get(RestAdminApplication.ZKCLIENT); + + String instanceSessionId = + ClusterRepresentationUtil.getInstanceSessionId(zkClient, + clusterName, + instanceName); + + Builder keyBuilder = new PropertyKey.Builder(clusterName); + String message = + ClusterRepresentationUtil.getInstancePropertiesAsString(zkClient, + clusterName, + keyBuilder.stateTransitionStatus(instanceName, + instanceSessionId, + resourceGroup), + // instanceSessionId + // + "__" + // + resourceGroup, + MediaType.APPLICATION_JSON); + StringRepresentation representation = + new StringRepresentation(message, MediaType.APPLICATION_JSON); + return representation; + } +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StatusUpdatesResource.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StatusUpdatesResource.java b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StatusUpdatesResource.java new file mode 100644 index 0000000..80a51df --- /dev/null +++ b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/StatusUpdatesResource.java @@ -0,0 +1,103 @@ +/** + * Copyright (C) 2012 LinkedIn Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.helix.webapp.resources; + +import java.io.IOException; + +import org.apache.helix.PropertyType; +import org.apache.helix.manager.zk.ZkClient; +import org.apache.helix.webapp.RestAdminApplication; +import org.apache.log4j.Logger; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.map.JsonMappingException; +import org.restlet.Context; +import org.restlet.data.MediaType; +import org.restlet.data.Request; +import org.restlet.data.Response; +import org.restlet.resource.Representation; +import org.restlet.resource.Resource; +import org.restlet.resource.StringRepresentation; +import org.restlet.resource.Variant; + + +public class StatusUpdatesResource extends Resource +{ + private final static Logger LOG = Logger.getLogger(StatusUpdatesResource.class); + + public StatusUpdatesResource(Context context, Request request, Response response) + { + super(context, request, response); + getVariants().add(new Variant(MediaType.TEXT_PLAIN)); + getVariants().add(new Variant(MediaType.APPLICATION_JSON)); + } + + @Override + public boolean allowGet() + { + return true; + } + + @Override + public boolean allowPost() + { + return false; + } + + @Override + public boolean allowPut() + { + return false; + } + + @Override + public boolean allowDelete() + { + return false; + } + + @Override + public Representation represent(Variant variant) + { + StringRepresentation presentation = null; + try + { + String clusterName = (String) getRequest().getAttributes().get("clusterName"); + String instanceName = (String) getRequest().getAttributes().get("instanceName"); + presentation = getInstanceErrorsRepresentation( clusterName, instanceName); + } + catch (Exception e) + { + String error = ClusterRepresentationUtil.getErrorAsJsonStringFromException(e); + presentation = new StringRepresentation(error, MediaType.APPLICATION_JSON); + + LOG.error("", e); + } + return presentation; + } + + StringRepresentation getInstanceErrorsRepresentation( String clusterName, String instanceName) throws JsonGenerationException, JsonMappingException, IOException + { + ZkClient zkClient = (ZkClient)getContext().getAttributes().get(RestAdminApplication.ZKCLIENT); + String instanceSessionId = ClusterRepresentationUtil.getInstanceSessionId(zkClient, clusterName, instanceName); + + String message = ClusterRepresentationUtil.getInstancePropertyNameListAsString(zkClient, clusterName, instanceName, PropertyType.CURRENTSTATES, instanceSessionId, MediaType.APPLICATION_JSON); + + StringRepresentation representation = new StringRepresentation(message, MediaType.APPLICATION_JSON); + + return representation; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/ZkChildResource.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/ZkChildResource.java b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/ZkChildResource.java new file mode 100644 index 0000000..1fab560 --- /dev/null +++ b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/ZkChildResource.java @@ -0,0 +1,158 @@ +package org.apache.helix.webapp.resources; + +import java.util.List; + +import org.apache.helix.ZNRecord; +import org.apache.helix.manager.zk.ZkClient; +import org.apache.helix.webapp.RestAdminApplication; +import org.apache.log4j.Logger; +import org.apache.zookeeper.data.Stat; +import org.restlet.Context; +import org.restlet.data.MediaType; +import org.restlet.data.Request; +import org.restlet.data.Response; +import org.restlet.data.Status; +import org.restlet.resource.Representation; +import org.restlet.resource.Resource; +import org.restlet.resource.StringRepresentation; +import org.restlet.resource.Variant; + + +public class ZkChildResource extends Resource +{ + private final static Logger LOG = Logger.getLogger(ZkChildResource.class); + + public ZkChildResource(Context context, Request request, Response response) + { + super(context, request, response); + getVariants().add(new Variant(MediaType.TEXT_PLAIN)); + getVariants().add(new Variant(MediaType.APPLICATION_JSON)); + } + + @Override + public boolean allowGet() + { + return true; + } + + @Override + public boolean allowPost() + { + return false; + } + + @Override + public boolean allowPut() + { + return false; + } + + @Override + public boolean allowDelete() + { + return true; + } + + private String getZKPath() + { + String relativeRef = getRequest().getResourceRef().getRelativeRef().toString(); + if (relativeRef.equals(".")) + { + relativeRef = ""; + } + + // strip off trailing "/" + while (relativeRef.endsWith("/")) + { + relativeRef = relativeRef.substring(0, relativeRef.length() - 1); + } + + return "/" + relativeRef; + } + + @Override + public Representation represent(Variant variant) + { + StringRepresentation presentation = null; + String zkPath = getZKPath(); + + try + { + ZkClient zkClient = + (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT); + ZNRecord result = readZkChild(zkPath, zkClient); + + presentation = + new StringRepresentation(ClusterRepresentationUtil.ZNRecordToJson(result), + MediaType.APPLICATION_JSON); + } + catch (Exception e) + { + String error = ClusterRepresentationUtil.getErrorAsJsonStringFromException(e); + presentation = new StringRepresentation(error, MediaType.APPLICATION_JSON); + + LOG.error("Error in read zkPath: " + zkPath, e); + } + + return presentation; + } + + private ZNRecord readZkChild(String zkPath, ZkClient zkClient) + { + ZNRecord result = null; + + // read data and stat + Stat stat = new Stat(); + ZNRecord data = zkClient.readDataAndStat(zkPath, stat, true); + if (data != null) + { + result = data; + } + else + { + result = new ZNRecord(""); + } + + // read childrenList + List children = zkClient.getChildren(zkPath); + if (children != null && children.size() > 0) + { + result.setSimpleField("numChildren", "" + children.size()); + result.setListField("childrenList", children); + } else + { + result.setSimpleField("numChildren", "" + 0); + } + return result; + } + + @Override + public void removeRepresentations() + { + String zkPath = getZKPath(); + try + { + ZkClient zkClient = + (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT); + + List childNames = zkClient.getChildren(zkPath); + if (childNames != null) + { + for (String childName : childNames) + { + String childPath = zkPath.equals("/")? "/" + childName : zkPath + "/" + childName; + zkClient.deleteRecursive(childPath); + } + } + + getResponse().setStatus(Status.SUCCESS_OK); + } + catch (Exception e) + { + getResponse().setEntity(ClusterRepresentationUtil.getErrorAsJsonStringFromException(e), + MediaType.APPLICATION_JSON); + getResponse().setStatus(Status.SUCCESS_OK); + LOG.error("Error in delete zkChild: " + zkPath, e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/ZkPathResource.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/ZkPathResource.java b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/ZkPathResource.java new file mode 100644 index 0000000..ff29031 --- /dev/null +++ b/helix-admin-webapp/src/main/java/org/apache/helix/webapp/resources/ZkPathResource.java @@ -0,0 +1,213 @@ +/** + * Copyright (C) 2012 LinkedIn Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.helix.webapp.resources; + +import java.util.Date; +import java.util.List; + +import org.apache.helix.HelixException; +import org.apache.helix.ZNRecord; +import org.apache.helix.manager.zk.ZkBaseDataAccessor; +import org.apache.helix.manager.zk.ZkClient; +import org.apache.helix.tools.ClusterSetup; +import org.apache.helix.webapp.RestAdminApplication; +import org.apache.log4j.Logger; +import org.apache.zookeeper.data.Stat; +import org.restlet.Context; +import org.restlet.data.MediaType; +import org.restlet.data.Request; +import org.restlet.data.Response; +import org.restlet.data.Status; +import org.restlet.resource.Representation; +import org.restlet.resource.Resource; +import org.restlet.resource.StringRepresentation; +import org.restlet.resource.Variant; + + +public class ZkPathResource extends Resource +{ + private final static Logger LOG = Logger.getLogger(ZkPathResource.class); + + public ZkPathResource(Context context, Request request, Response response) + { + super(context, request, response); + getVariants().add(new Variant(MediaType.TEXT_PLAIN)); + getVariants().add(new Variant(MediaType.APPLICATION_JSON)); + } + + @Override + public boolean allowGet() + { + return true; + } + + @Override + public boolean allowPost() + { + return true; + } + + @Override + public boolean allowPut() + { + return false; + } + + @Override + public boolean allowDelete() + { + return true; + } + + private String getZKPath() + { + String relativeRef = getRequest().getResourceRef().getRelativeRef().toString(); + if (relativeRef.equals(".")) + { + relativeRef = ""; + } + + // strip off trailing "/" + while (relativeRef.endsWith("/")) + { + relativeRef = relativeRef.substring(0, relativeRef.length() - 1); + } + + return "/" + relativeRef; + } + + @Override + public void acceptRepresentation(Representation entity) + { + String zkPath = getZKPath(); + + try + { + JsonParameters jsonParameters = new JsonParameters(entity); + String command = jsonParameters.getCommand(); + + ZkClient zkClient = + (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT); + + if (command.equalsIgnoreCase(JsonParameters.ZK_DELETE_CHILDREN)) + { + List childNames = zkClient.getChildren(zkPath); + if (childNames != null) + { + for (String childName : childNames) + { + String childPath = zkPath.equals("/")? "/" + childName : zkPath + "/" + childName; + zkClient.deleteRecursive(childPath); + } + } + } + else + { + throw new HelixException("Unsupported command: " + command + + ". Should be one of [" + JsonParameters.ZK_DELETE_CHILDREN + "]"); + } + + getResponse().setStatus(Status.SUCCESS_OK); + } + catch (Exception e) + { + getResponse().setEntity(ClusterRepresentationUtil.getErrorAsJsonStringFromException(e), + MediaType.APPLICATION_JSON); + getResponse().setStatus(Status.SUCCESS_OK); + LOG.error("Error in post zkPath: " + zkPath, e); + } + } + + @Override + public Representation represent(Variant variant) + { + StringRepresentation presentation = null; + String zkPath = getZKPath(); + + try + { + ZkClient zkClient = + (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT); + ZNRecord result = readZkDataStatAndChild(zkPath, zkClient); + + presentation = + new StringRepresentation(ClusterRepresentationUtil.ZNRecordToJson(result), + MediaType.APPLICATION_JSON); + } + catch (Exception e) + { + String error = ClusterRepresentationUtil.getErrorAsJsonStringFromException(e); + presentation = new StringRepresentation(error, MediaType.APPLICATION_JSON); + + LOG.error("Error in read zkPath: " + zkPath, e); + } + + return presentation; + } + + private ZNRecord readZkDataStatAndChild(String zkPath, ZkClient zkClient) + { + ZNRecord result = null; + + // read data and stat + Stat stat = new Stat(); + ZNRecord data = zkClient.readDataAndStat(zkPath, stat, true); + if (data != null) + { + result = data; + } + else + { + result = new ZNRecord(""); + } + result.setSimpleField("zkPath", zkPath); + result.setSimpleField("stat", stat.toString()); + result.setSimpleField("numChildren", "" + stat.getNumChildren()); + result.setSimpleField("ctime", "" + new Date(stat.getCtime())); + result.setSimpleField("mtime", "" + new Date(stat.getMtime())); + result.setSimpleField("dataLength", "" + stat.getDataLength()); + + // read childrenList + List children = zkClient.getChildren(zkPath); + if (children != null && children.size() > 0) + { + result.setListField("childrenList", children); + } + return result; + } + + @Override + public void removeRepresentations() + { + String zkPath = getZKPath(); + try + { + ZkClient zkClient = + (ZkClient) getContext().getAttributes().get(RestAdminApplication.ZKCLIENT); + zkClient.deleteRecursive(zkPath); + + getResponse().setStatus(Status.SUCCESS_OK); + } + catch (Exception e) + { + getResponse().setEntity(ClusterRepresentationUtil.getErrorAsJsonStringFromException(e), + MediaType.APPLICATION_JSON); + getResponse().setStatus(Status.SUCCESS_OK); + LOG.error("Error in delete zkPath: " + zkPath, e); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/test/java/org/apache/helix/tools/AdminTestBase.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/test/java/org/apache/helix/tools/AdminTestBase.java b/helix-admin-webapp/src/test/java/org/apache/helix/tools/AdminTestBase.java new file mode 100644 index 0000000..c8eede8 --- /dev/null +++ b/helix-admin-webapp/src/test/java/org/apache/helix/tools/AdminTestBase.java @@ -0,0 +1,69 @@ +package org.apache.helix.tools; + +import java.util.logging.Level; + +import org.I0Itec.zkclient.ZkServer; +import org.apache.helix.TestHelper; +import org.apache.helix.manager.zk.ZNRecordSerializer; +import org.apache.helix.manager.zk.ZkClient; +import org.apache.helix.tools.ClusterSetup; +import org.apache.helix.tools.AdminTestHelper.AdminThread; +import org.apache.helix.util.ZKClientPool; +import org.apache.log4j.Logger; +import org.testng.AssertJUnit; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.BeforeSuite; + + +public class AdminTestBase +{ + private static Logger LOG = Logger.getLogger(AdminTestBase.class); + public static final String ZK_ADDR = "localhost:2187"; + protected final static int ADMIN_PORT = 2202; + + protected static ZkServer _zkServer; + protected static ZkClient _gZkClient; + protected static ClusterSetup _gSetupTool; + + static AdminThread _adminThread; + + @BeforeSuite + public void beforeSuite() throws Exception + { + // TODO: use logging.properties file to config java.util.logging.Logger levels + java.util.logging.Logger topJavaLogger = java.util.logging.Logger.getLogger(""); + topJavaLogger.setLevel(Level.WARNING); + + // start zk + _zkServer = TestHelper.startZkSever(ZK_ADDR); + AssertJUnit.assertTrue(_zkServer != null); + ZKClientPool.reset(); + + _gZkClient = new ZkClient(ZK_ADDR); + _gZkClient.setZkSerializer(new ZNRecordSerializer()); + _gSetupTool = new ClusterSetup(ZK_ADDR); + + // start admin + _adminThread = new AdminThread(ZK_ADDR, ADMIN_PORT); + _adminThread.start(); + + // wait for the web service to start + Thread.sleep(100); + } + + @AfterSuite + public void afterSuite() + { + // System.out.println("START AdminTestBase.afterSuite() at " + new Date(System.currentTimeMillis())); + // stop admin + _adminThread.stop(); + + // stop zk + ZKClientPool.reset(); + _gZkClient.close(); + + TestHelper.stopZkServer(_zkServer); + // System.out.println("END AdminTestBase.afterSuite() at " + new Date(System.currentTimeMillis())); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/test/java/org/apache/helix/tools/AdminTestHelper.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/test/java/org/apache/helix/tools/AdminTestHelper.java b/helix-admin-webapp/src/test/java/org/apache/helix/tools/AdminTestHelper.java new file mode 100644 index 0000000..79709eb --- /dev/null +++ b/helix-admin-webapp/src/test/java/org/apache/helix/tools/AdminTestHelper.java @@ -0,0 +1,64 @@ +package org.apache.helix.tools; + +import java.util.concurrent.CountDownLatch; + +import org.apache.helix.webapp.HelixAdminWebApp; + + +public class AdminTestHelper +{ + + public static class AdminThread + { + Thread _adminThread; + CountDownLatch _stopCountDown = new CountDownLatch(1); + String _zkAddr; + int _port; + + public AdminThread(String zkAddr, int port) + { + _zkAddr = zkAddr; + _port = port; + } + + public void start() + { + Thread adminThread = new Thread(new Runnable() + { + @Override + public void run() + { + HelixAdminWebApp app = null; + try + { + app = new HelixAdminWebApp(_zkAddr, _port); + app.start(); + // Thread.currentThread().join(); + _stopCountDown.await(); + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + if (app != null) + { +// System.err.println("Stopping HelixAdminWebApp"); + app.stop(); + } + } + } + }); + + adminThread.setDaemon(true); + adminThread.start(); + } + + public void stop() + { + _stopCountDown.countDown(); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestHelixAdminScenariosRest.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestHelixAdminScenariosRest.java b/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestHelixAdminScenariosRest.java new file mode 100644 index 0000000..5133705 --- /dev/null +++ b/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestHelixAdminScenariosRest.java @@ -0,0 +1,741 @@ +package org.apache.helix.tools; + +/* + * Simulate all the admin tasks needed by using command line tool + * + * */ +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.helix.HelixDataAccessor; +import org.apache.helix.TestHelper; +import org.apache.helix.ZNRecord; +import org.apache.helix.TestHelper.StartCMResult; +import org.apache.helix.controller.HelixControllerMain; +import org.apache.helix.manager.zk.ZKUtil; +import org.apache.helix.model.ExternalView; +import org.apache.helix.model.LiveInstance; +import org.apache.helix.tools.ClusterSetup; +import org.apache.helix.tools.ClusterStateVerifier; +import org.apache.helix.tools.ClusterStateVerifier.BestPossAndExtViewZkVerifier; +import org.apache.helix.tools.ClusterStateVerifier.MasterNbInExtViewVerifier; +import org.apache.helix.webapp.RestAdminApplication; +import org.apache.helix.webapp.resources.ClusterRepresentationUtil; +import org.apache.helix.webapp.resources.JsonParameters; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; +import org.restlet.Client; +import org.restlet.Component; +import org.restlet.data.MediaType; +import org.restlet.data.Method; +import org.restlet.data.Protocol; +import org.restlet.data.Reference; +import org.restlet.data.Request; +import org.restlet.data.Response; +import org.restlet.data.Status; +import org.restlet.resource.Representation; +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class TestHelixAdminScenariosRest extends AdminTestBase +{ + Map _startCMResultMap = new HashMap(); + RestAdminApplication _adminApp; + Component _component; + + public static String ObjectToJson(Object object) throws JsonGenerationException, + JsonMappingException, + IOException + { + ObjectMapper mapper = new ObjectMapper(); + SerializationConfig serializationConfig = mapper.getSerializationConfig(); + serializationConfig.set(SerializationConfig.Feature.INDENT_OUTPUT, true); + + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, object); + + return sw.toString(); + } + + public static T JsonToObject(Class clazz, String jsonString) throws JsonParseException, + JsonMappingException, + IOException + { + StringReader sr = new StringReader(jsonString); + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(sr, clazz); + } + + @Test + public void testAddDeleteClusterAndInstanceAndResource() throws Exception + { + // Helix bug helix-102 + // ZKPropertyTransferServer.PERIOD = 500; + // ZkPropertyTransferClient.SEND_PERIOD = 500; + // ZKPropertyTransferServer.getInstance().init(19999, ZK_ADDR); + + /** ======================= Add clusters ============================== */ + + testAddCluster(); + + /** ================= Add / drop some resources =========================== */ + + testAddResource(); + + /** ====================== Add / delete instances =========================== */ + + testAddInstance(); + + /** ===================== Rebalance resource =========================== */ + + testRebalanceResource(); + + /** ==================== start the clusters ============================= */ + + testStartCluster(); + + /** ==================== drop add resource in live clusters =================== */ + testDropAddResource(); + + /** ======================Operations with live node ============================ */ + + testInstanceOperations(); + + /** ======================Operations with partitions ============================ */ + + testEnablePartitions(); + + /** ============================ expand cluster =========================== */ + + testExpandCluster(); + + /** ============================ deactivate cluster =========================== */ + testDeactivateCluster(); + + // wait all zk callbacks done + Thread.sleep(1000); + } + + static String assertSuccessPostOperation(String url, + Map jsonParameters, + boolean hasException) throws IOException + { + Reference resourceRef = new Reference(url); + + Request request = new Request(Method.POST, resourceRef); + request.setEntity(JsonParameters.JSON_PARAMETERS + "=" + + ClusterRepresentationUtil.ObjectToJson(jsonParameters), + MediaType.APPLICATION_ALL); + Client client = new Client(Protocol.HTTP); + Response response = client.handle(request); + Representation result = response.getEntity(); + StringWriter sw = new StringWriter(); + result.write(sw); + + Assert.assertTrue(response.getStatus().getCode() == Status.SUCCESS_OK.getCode()); + Assert.assertTrue(hasException == sw.toString().toLowerCase().contains("exception")); + return sw.toString(); + } + + static String assertSuccessPostOperation(String url, + Map jsonParameters, + Map extraForm, + boolean hasException) throws IOException + { + Reference resourceRef = new Reference(url); + + Request request = new Request(Method.POST, resourceRef); + String entity = + JsonParameters.JSON_PARAMETERS + "=" + + ClusterRepresentationUtil.ObjectToJson(jsonParameters); + for (String key : extraForm.keySet()) + { + entity = entity + "&" + (key + "=" + extraForm.get(key)); + } + request.setEntity(entity, MediaType.APPLICATION_ALL); + Client client = new Client(Protocol.HTTP); + Response response = client.handle(request); + Representation result = response.getEntity(); + StringWriter sw = new StringWriter(); + result.write(sw); + + Assert.assertTrue(response.getStatus().getCode() == Status.SUCCESS_OK.getCode()); + Assert.assertTrue(hasException == sw.toString().toLowerCase().contains("exception")); + return sw.toString(); + } + + void deleteUrl(String url, boolean hasException) throws IOException + { + Reference resourceRef = new Reference(url); + Request request = new Request(Method.DELETE, resourceRef); + Client client = new Client(Protocol.HTTP); + Response response = client.handle(request); + Representation result = response.getEntity(); + StringWriter sw = new StringWriter(); + result.write(sw); + Assert.assertTrue(hasException == sw.toString().toLowerCase().contains("exception")); + } + + String getUrl(String url) throws IOException + { + Reference resourceRef = new Reference(url); + Request request = new Request(Method.GET, resourceRef); + Client client = new Client(Protocol.HTTP); + Response response = client.handle(request); + Representation result = response.getEntity(); + StringWriter sw = new StringWriter(); + result.write(sw); + return sw.toString(); + } + + String getClusterUrl(String cluster) + { + return "http://localhost:" + ADMIN_PORT + "/clusters" + "/" + cluster; + } + + String getInstanceUrl(String cluster, String instance) + { + return "http://localhost:" + ADMIN_PORT + "/clusters/" + cluster + "/instances/" + + instance; + } + + String getResourceUrl(String cluster, String resourceGroup) + { + return "http://localhost:" + ADMIN_PORT + "/clusters/" + cluster + "/resourceGroups/" + + resourceGroup; + } + + void assertClusterSetupException(String command) + { + boolean exceptionThrown = false; + try + { + ClusterSetup.processCommandLineArgs(command.split(" ")); + } + catch (Exception e) + { + exceptionThrown = true; + } + Assert.assertTrue(exceptionThrown); + } + + public void testAddCluster() throws Exception + { + String url = "http://localhost:" + ADMIN_PORT + "/clusters"; + Map paraMap = new HashMap(); + + // Normal add + paraMap.put(JsonParameters.CLUSTER_NAME, "clusterTest"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addCluster); + + String response = assertSuccessPostOperation(url, paraMap, false); + Assert.assertTrue(response.contains("clusterTest")); + + // malformed cluster name + paraMap.put(JsonParameters.CLUSTER_NAME, "/ClusterTest"); + response = assertSuccessPostOperation(url, paraMap, true); + + // Add the grand cluster + paraMap.put(JsonParameters.CLUSTER_NAME, "Klazt3rz"); + response = assertSuccessPostOperation(url, paraMap, false); + Assert.assertTrue(response.contains("Klazt3rz")); + + paraMap.put(JsonParameters.CLUSTER_NAME, "\\ClusterTest"); + response = assertSuccessPostOperation(url, paraMap, false); + Assert.assertTrue(response.contains("\\ClusterTest")); + + // Add already exist cluster + paraMap.put(JsonParameters.CLUSTER_NAME, "clusterTest"); + response = assertSuccessPostOperation(url, paraMap, true); + + // delete cluster without resource and instance + Assert.assertTrue(ZKUtil.isClusterSetup("Klazt3rz", _gZkClient)); + Assert.assertTrue(ZKUtil.isClusterSetup("clusterTest", _gZkClient)); + Assert.assertTrue(ZKUtil.isClusterSetup("\\ClusterTest", _gZkClient)); + + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.dropCluster); + + String clusterUrl = getClusterUrl("\\ClusterTest"); + deleteUrl(clusterUrl, false); + + String clustersUrl = "http://localhost:" + ADMIN_PORT + "/clusters"; + response = getUrl(clustersUrl); + + clusterUrl = getClusterUrl("clusterTest1"); + deleteUrl(clusterUrl, false); + response = getUrl(clustersUrl); + Assert.assertFalse(response.contains("clusterTest1")); + + clusterUrl = getClusterUrl("clusterTest"); + deleteUrl(clusterUrl, false); + response = getUrl(clustersUrl); + Assert.assertFalse(response.contains("clusterTest")); + + clusterUrl = getClusterUrl("clusterTestOK"); + deleteUrl(clusterUrl, false); + + Assert.assertFalse(_gZkClient.exists("/clusterTest")); + Assert.assertFalse(_gZkClient.exists("/clusterTest1")); + Assert.assertFalse(_gZkClient.exists("/clusterTestOK")); + + paraMap.put(JsonParameters.CLUSTER_NAME, "clusterTest1"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addCluster); + response = assertSuccessPostOperation(url, paraMap, false); + response = getUrl(clustersUrl); + Assert.assertTrue(response.contains("clusterTest1")); + } + + public void testAddResource() throws Exception + { + String reourcesUrl = + "http://localhost:" + ADMIN_PORT + "/clusters/clusterTest1/resourceGroups"; + + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.RESOURCE_GROUP_NAME, "db_22"); + paraMap.put(JsonParameters.STATE_MODEL_DEF_REF, "MasterSlave"); + paraMap.put(JsonParameters.PARTITIONS, "144"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addResource); + + String response = assertSuccessPostOperation(reourcesUrl, paraMap, false); + Assert.assertTrue(response.contains("db_22")); + + paraMap.put(JsonParameters.RESOURCE_GROUP_NAME, "db_11"); + paraMap.put(JsonParameters.STATE_MODEL_DEF_REF, "MasterSlave"); + paraMap.put(JsonParameters.PARTITIONS, "44"); + + response = assertSuccessPostOperation(reourcesUrl, paraMap, false); + Assert.assertTrue(response.contains("db_11")); + + // Add duplicate resource + paraMap.put(JsonParameters.RESOURCE_GROUP_NAME, "db_22"); + paraMap.put(JsonParameters.STATE_MODEL_DEF_REF, "OnlineOffline"); + paraMap.put(JsonParameters.PARTITIONS, "55"); + + response = assertSuccessPostOperation(reourcesUrl, paraMap, true); + + // drop resource now + String resourceUrl = getResourceUrl("clusterTest1", "db_11"); + deleteUrl(resourceUrl, false); + Assert.assertFalse(_gZkClient.exists("/clusterTest1/IDEALSTATES/db_11")); + + paraMap.put(JsonParameters.RESOURCE_GROUP_NAME, "db_11"); + paraMap.put(JsonParameters.STATE_MODEL_DEF_REF, "MasterSlave"); + paraMap.put(JsonParameters.PARTITIONS, "44"); + response = assertSuccessPostOperation(reourcesUrl, paraMap, false); + Assert.assertTrue(response.contains("db_11")); + + Assert.assertTrue(_gZkClient.exists("/clusterTest1/IDEALSTATES/db_11")); + } + + private void testDeactivateCluster() throws Exception, + InterruptedException + { + HelixDataAccessor accessor; + String path; + // deactivate cluster + String clusterUrl = getClusterUrl("clusterTest1"); + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.ENABLED, "false"); + paraMap.put(JsonParameters.GRAND_CLUSTER, "Klazt3rz"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.activateCluster); + + String response = assertSuccessPostOperation(clusterUrl, paraMap, false); + Thread.sleep(6000); + Assert.assertFalse(_gZkClient.exists("/Klazt3rz/IDEALSTATES/clusterTest1")); + + accessor = _startCMResultMap.get("localhost_1231")._manager.getHelixDataAccessor(); + path = accessor.keyBuilder().controllerLeader().getPath(); + Assert.assertFalse(_gZkClient.exists(path)); + + deleteUrl(clusterUrl, true); + + Assert.assertTrue(_gZkClient.exists("/clusterTest1")); + // leader node should be gone + for (StartCMResult result : _startCMResultMap.values()) + { + result._manager.disconnect(); + result._thread.interrupt(); + } + deleteUrl(clusterUrl, false); + + Assert.assertFalse(_gZkClient.exists("/clusterTest1")); + } + + private void testDropAddResource() throws Exception + { + ZNRecord record = + _gSetupTool._admin.getResourceIdealState("clusterTest1", "db_11").getRecord(); + String x = ObjectToJson(record); + + FileWriter fos = new FileWriter("/tmp/temp.log"); + PrintWriter pw = new PrintWriter(fos); + pw.write(x); + pw.close(); + + String resourceUrl = getResourceUrl("clusterTest1", "db_11"); + deleteUrl(resourceUrl, false); + + boolean verifyResult = + ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR, + "clusterTest1")); + Assert.assertTrue(verifyResult); + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addResource); + paraMap.put(JsonParameters.RESOURCE_GROUP_NAME, "db_11"); + paraMap.put(JsonParameters.PARTITIONS, "22"); + paraMap.put(JsonParameters.STATE_MODEL_DEF_REF, "MasterSlave"); + String response = + assertSuccessPostOperation(getClusterUrl("clusterTest1") + "/resourceGroups", + paraMap, + false); + + String idealStateUrl = getResourceUrl("clusterTest1", "db_11") + "/idealState"; + Assert.assertTrue(response.contains("db_11")); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addIdealState); + Map extraform = new HashMap(); + extraform.put(JsonParameters.NEW_IDEAL_STATE, x); + response = assertSuccessPostOperation(idealStateUrl, paraMap, extraform, false); + + verifyResult = + ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR, + "clusterTest1")); + Assert.assertTrue(verifyResult); + + ZNRecord record2 = + _gSetupTool._admin.getResourceIdealState("clusterTest1", "db_11").getRecord(); + Assert.assertTrue(record2.equals(record)); + } + + private void testExpandCluster() throws Exception + { + boolean verifyResult; + + String clusterUrl = getClusterUrl("clusterTest1"); + String instancesUrl = clusterUrl + "/instances"; + + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.INSTANCE_NAMES, + "localhost:12331;localhost:12341;localhost:12351;localhost:12361"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addInstance); + + String response = assertSuccessPostOperation(instancesUrl, paraMap, false); + String[] hosts = + "localhost:12331;localhost:12341;localhost:12351;localhost:12361".split(";"); + for (String host : hosts) + { + Assert.assertTrue(response.contains(host.replace(':', '_'))); + } + paraMap.clear(); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.expandCluster); + response = assertSuccessPostOperation(clusterUrl, paraMap, false); + + for (int i = 3; i <= 6; i++) + { + StartCMResult result = + TestHelper.startDummyProcess(ZK_ADDR, "clusterTest1", "localhost_123" + i + "1"); + _startCMResultMap.put("localhost_123" + i + "1", result); + } + + verifyResult = + ClusterStateVerifier.verifyByZkCallback(new MasterNbInExtViewVerifier(ZK_ADDR, + "clusterTest1")); + Assert.assertTrue(verifyResult); + + verifyResult = + ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR, + "clusterTest1")); + Assert.assertTrue(verifyResult); + } + + private void testEnablePartitions() throws IOException, + InterruptedException + { + HelixDataAccessor accessor; + accessor = _startCMResultMap.get("localhost_1231")._manager.getHelixDataAccessor(); + // drop node should fail as not disabled + String hostName = "localhost_1231"; + String instanceUrl = getInstanceUrl("clusterTest1", hostName); + ExternalView ev = accessor.getProperty(accessor.keyBuilder().externalView("db_11")); + + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.enablePartition); + paraMap.put(JsonParameters.ENABLED, "false"); + paraMap.put(JsonParameters.PARTITION, "db_11_0;db_11_15"); + paraMap.put(JsonParameters.RESOURCE, "db_11"); + + String response = assertSuccessPostOperation(instanceUrl, paraMap, false); + Assert.assertTrue(response.contains("DISABLED_PARTITION")); + Assert.assertTrue(response.contains("db_11_0")); + Assert.assertTrue(response.contains("db_11_15")); + + boolean verifyResult = + ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR, + "clusterTest1")); + Assert.assertTrue(verifyResult); + + ev = accessor.getProperty(accessor.keyBuilder().externalView("db_11")); + Assert.assertEquals(ev.getStateMap("db_11_0").get(hostName), "OFFLINE"); + Assert.assertEquals(ev.getStateMap("db_11_15").get(hostName), "OFFLINE"); + + paraMap.put(JsonParameters.ENABLED, "true"); + response = assertSuccessPostOperation(instanceUrl, paraMap, false); + Assert.assertFalse(response.contains("db_11_0")); + Assert.assertFalse(response.contains("db_11_15")); + + verifyResult = + ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR, + "clusterTest1")); + Assert.assertTrue(verifyResult); + + ev = accessor.getProperty(accessor.keyBuilder().externalView("db_11")); + Assert.assertEquals(ev.getStateMap("db_11_0").get(hostName), "MASTER"); + Assert.assertEquals(ev.getStateMap("db_11_15").get(hostName), "SLAVE"); + } + + private void testInstanceOperations() throws Exception + { + HelixDataAccessor accessor; + // drop node should fail as not disabled + String instanceUrl = getInstanceUrl("clusterTest1", "localhost_1232"); + deleteUrl(instanceUrl, true); + + // disabled node + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.enableInstance); + paraMap.put(JsonParameters.ENABLED, "false"); + String response = assertSuccessPostOperation(instanceUrl, paraMap, false); + Assert.assertTrue(response.contains("false")); + + // Cannot drop / swap + deleteUrl(instanceUrl, true); + + String instancesUrl = getClusterUrl("clusterTest1") + "/instances"; + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.swapInstance); + paraMap.put(JsonParameters.OLD_INSTANCE, "localhost_1232"); + paraMap.put(JsonParameters.NEW_INSTANCE, "localhost_12320"); + response = assertSuccessPostOperation(instancesUrl, paraMap, true); + + // disconnect the node + _startCMResultMap.get("localhost_1232")._manager.disconnect(); + _startCMResultMap.get("localhost_1232")._thread.interrupt(); + + // add new node then swap instance + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addInstance); + paraMap.put(JsonParameters.INSTANCE_NAME, "localhost_12320"); + response = assertSuccessPostOperation(instancesUrl, paraMap, false); + Assert.assertTrue(response.contains("localhost_12320")); + + // swap instance. The instance get swapped out should not exist anymore + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.swapInstance); + paraMap.put(JsonParameters.OLD_INSTANCE, "localhost_1232"); + paraMap.put(JsonParameters.NEW_INSTANCE, "localhost_12320"); + response = assertSuccessPostOperation(instancesUrl, paraMap, false); + Assert.assertTrue(response.contains("localhost_12320")); + Assert.assertFalse(response.contains("localhost_1232\"")); + + accessor = _startCMResultMap.get("localhost_1231")._manager.getHelixDataAccessor(); + String path = accessor.keyBuilder().instanceConfig("localhost_1232").getPath(); + Assert.assertFalse(_gZkClient.exists(path)); + + _startCMResultMap.put("localhost_12320", + TestHelper.startDummyProcess(ZK_ADDR, + "clusterTest1", + "localhost_12320")); + } + + private void testStartCluster() throws Exception, + InterruptedException + { + // start mock nodes + for (int i = 0; i < 6; i++) + { + StartCMResult result = + TestHelper.startDummyProcess(ZK_ADDR, "clusterTest1", "localhost_123" + i); + _startCMResultMap.put("localhost_123" + i, result); + } + + // start controller nodes + for (int i = 0; i < 2; i++) + { + StartCMResult result = + TestHelper.startController("Klazt3rz", + "controller_900" + i, + ZK_ADDR, + HelixControllerMain.DISTRIBUTED); + + _startCMResultMap.put("controller_900" + i, result); + } + Thread.sleep(100); + + // activate clusters + // wrong grand clustername + + String clusterUrl = getClusterUrl("clusterTest1"); + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.ENABLED, "true"); + paraMap.put(JsonParameters.GRAND_CLUSTER, "Klazters"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.activateCluster); + + String response = assertSuccessPostOperation(clusterUrl, paraMap, true); + + // wrong cluster name + clusterUrl = getClusterUrl("clusterTest2"); + paraMap.put(JsonParameters.GRAND_CLUSTER, "Klazt3rz"); + response = assertSuccessPostOperation(clusterUrl, paraMap, true); + + paraMap.put(JsonParameters.ENABLED, "true"); + paraMap.put(JsonParameters.GRAND_CLUSTER, "Klazt3rz"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.activateCluster); + clusterUrl = getClusterUrl("clusterTest1"); + response = assertSuccessPostOperation(clusterUrl, paraMap, false); + Thread.sleep(500); + + deleteUrl(clusterUrl, true); + + // verify leader node + HelixDataAccessor accessor = + _startCMResultMap.get("controller_9001")._manager.getHelixDataAccessor(); + LiveInstance controllerLeader = + accessor.getProperty(accessor.keyBuilder().controllerLeader()); + Assert.assertTrue(controllerLeader.getInstanceName().startsWith("controller_900")); + + accessor = _startCMResultMap.get("localhost_1232")._manager.getHelixDataAccessor(); + LiveInstance leader = accessor.getProperty(accessor.keyBuilder().controllerLeader()); + Assert.assertTrue(leader.getInstanceName().startsWith("controller_900")); + + boolean verifyResult = + ClusterStateVerifier.verifyByZkCallback(new MasterNbInExtViewVerifier(ZK_ADDR, + "clusterTest1")); + Assert.assertTrue(verifyResult); + + verifyResult = + ClusterStateVerifier.verifyByZkCallback(new BestPossAndExtViewZkVerifier(ZK_ADDR, + "clusterTest1")); + Assert.assertTrue(verifyResult); + } + + private void testRebalanceResource() throws Exception + { + String resourceUrl = getResourceUrl("clusterTest1", "db_11"); + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.REPLICAS, "3"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.rebalance); + + String ISUrl = resourceUrl + "/idealState"; + String response = assertSuccessPostOperation(ISUrl, paraMap, false); + ZNRecord record = JsonToObject(ZNRecord.class, response); + Assert.assertTrue(record.getId().equalsIgnoreCase("db_11")); + Assert.assertTrue((((List) (record.getListFields().values().toArray()[0]))).size() == 3); + Assert.assertTrue((((Map) (record.getMapFields().values().toArray()[0]))).size() == 3); + + deleteUrl(resourceUrl, false); + + // re-add and rebalance + String reourcesUrl = + "http://localhost:" + ADMIN_PORT + "/clusters/clusterTest1/resourceGroups"; + response = getUrl(reourcesUrl); + Assert.assertFalse(response.contains("db_11")); + + paraMap = new HashMap(); + paraMap.put(JsonParameters.RESOURCE_GROUP_NAME, "db_11"); + paraMap.put(JsonParameters.STATE_MODEL_DEF_REF, "MasterSlave"); + paraMap.put(JsonParameters.PARTITIONS, "48"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addResource); + + response = assertSuccessPostOperation(reourcesUrl, paraMap, false); + Assert.assertTrue(response.contains("db_11")); + + ISUrl = resourceUrl + "/idealState"; + paraMap.put(JsonParameters.REPLICAS, "3"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.rebalance); + response = assertSuccessPostOperation(ISUrl, paraMap, false); + record = JsonToObject(ZNRecord.class, response); + Assert.assertTrue(record.getId().equalsIgnoreCase("db_11")); + Assert.assertTrue((((List) (record.getListFields().values().toArray()[0]))).size() == 3); + Assert.assertTrue((((Map) (record.getMapFields().values().toArray()[0]))).size() == 3); + + // rebalance with key prefix + resourceUrl = getResourceUrl("clusterTest1", "db_22"); + ISUrl = resourceUrl + "/idealState"; + paraMap.put(JsonParameters.REPLICAS, "2"); + paraMap.put(JsonParameters.RESOURCE_KEY_PREFIX, "alias"); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.rebalance); + response = assertSuccessPostOperation(ISUrl, paraMap, false); + record = JsonToObject(ZNRecord.class, response); + Assert.assertTrue(record.getId().equalsIgnoreCase("db_22")); + Assert.assertTrue((((List) (record.getListFields().values().toArray()[0]))).size() == 2); + Assert.assertTrue((((Map) (record.getMapFields().values().toArray()[0]))).size() == 2); + Assert.assertTrue((((String) (record.getMapFields().keySet().toArray()[0]))).startsWith("alias_")); + } + + private void testAddInstance() throws Exception + { + String clusterUrl = getClusterUrl("clusterTest1"); + Map paraMap = new HashMap(); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addInstance); + String response = null; + // Add instances to cluster + String instancesUrl = clusterUrl + "/instances"; + for (int i = 0; i < 3; i++) + { + + paraMap.put(JsonParameters.INSTANCE_NAME, "localhost:123" + i); + response = assertSuccessPostOperation(instancesUrl, paraMap, false); + Assert.assertTrue(response.contains(("localhost:123" + i).replace(':', '_'))); + } + paraMap.remove(JsonParameters.INSTANCE_NAME); + paraMap.put(JsonParameters.INSTANCE_NAMES, + "localhost:1233;localhost:1234;localhost:1235;localhost:1236"); + + response = assertSuccessPostOperation(instancesUrl, paraMap, false); + for (int i = 3; i <= 6; i++) + { + Assert.assertTrue(response.contains("localhost_123" + i)); + } + + // delete one node without disable + String instanceUrl = instancesUrl + "/localhost_1236"; + deleteUrl(instanceUrl, true); + response = getUrl(instancesUrl); + Assert.assertTrue(response.contains("localhost_1236")); + + // delete non-exist node + instanceUrl = instancesUrl + "/localhost_12367"; + deleteUrl(instanceUrl, true); + response = getUrl(instancesUrl); + Assert.assertFalse(response.contains("localhost_12367")); + + // disable node + instanceUrl = instancesUrl + "/localhost_1236"; + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.enableInstance); + paraMap.put(JsonParameters.ENABLED, "false"); + response = assertSuccessPostOperation(instanceUrl, paraMap, false); + Assert.assertTrue(response.contains("false")); + + deleteUrl(instanceUrl, false); + + // add node to controller cluster + paraMap.remove(JsonParameters.INSTANCE_NAME); + paraMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.addInstance); + paraMap.put(JsonParameters.INSTANCE_NAMES, "controller:9000;controller:9001"); + String controllerUrl = getClusterUrl("Klazt3rz") + "/instances"; + response = assertSuccessPostOperation(controllerUrl, paraMap, false); + Assert.assertTrue(response.contains("controller_9000")); + Assert.assertTrue(response.contains("controller_9001")); + + // add a dup host + paraMap.remove(JsonParameters.INSTANCE_NAMES); + paraMap.put(JsonParameters.INSTANCE_NAME, "localhost:1234"); + response = assertSuccessPostOperation(instancesUrl, paraMap, true); + } +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetInstance.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetInstance.java b/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetInstance.java new file mode 100644 index 0000000..3e91fad --- /dev/null +++ b/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetInstance.java @@ -0,0 +1,119 @@ +package org.apache.helix.tools; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.helix.TestHelper; +import org.apache.helix.mock.controller.ClusterController; +import org.apache.helix.mock.storage.MockParticipant; +import org.apache.helix.mock.storage.MockParticipant.ErrTransition; +import org.apache.helix.tools.ClusterSetup; +import org.apache.helix.tools.ClusterStateVerifier; +import org.apache.helix.webapp.resources.JsonParameters; +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class TestResetInstance extends AdminTestBase +{ + @Test + public void testResetInstance() throws Exception + { + String className = TestHelper.getTestClassName(); + String methodName = TestHelper.getTestMethodName(); + String clusterName = className + "_" + methodName; + final int n = 5; + + System.out.println("START " + clusterName + " at " + + new Date(System.currentTimeMillis())); + + TestHelper.setupCluster(clusterName, ZK_ADDR, 12918, // participant port + "localhost", // participant name prefix + "TestDB", // resource name prefix + 1, // resources + 10, // partitions per resource + n, // number of nodes + 3, // replicas + "MasterSlave", + true); // do rebalance + +// // start admin thread +// AdminThread adminThread = new AdminThread(ZK_ADDR, _port); +// adminThread.start(); + + // start controller + ClusterController controller = + new ClusterController(clusterName, "controller_0", ZK_ADDR); + controller.syncStart(); + + Map> errPartitions = new HashMap>() + { + { + put("SLAVE-MASTER", TestHelper.setOf("TestDB0_4")); + put("OFFLINE-SLAVE", TestHelper.setOf("TestDB0_8")); + } + }; + + // start mock participants + MockParticipant[] participants = new MockParticipant[n]; + for (int i = 0; i < n; i++) + { + String instanceName = "localhost_" + (12918 + i); + + if (i == 0) + { + participants[i] = + new MockParticipant(clusterName, + instanceName, + ZK_ADDR, + new ErrTransition(errPartitions)); + } + else + { + participants[i] = new MockParticipant(clusterName, instanceName, ZK_ADDR); + } + participants[i].syncStart(); + } + + // verify cluster + Map> errStateMap = + new HashMap>(); + errStateMap.put("TestDB0", new HashMap()); + errStateMap.get("TestDB0").put("TestDB0_4", "localhost_12918"); + errStateMap.get("TestDB0").put("TestDB0_8", "localhost_12918"); + boolean result = + ClusterStateVerifier.verifyByZkCallback((new ClusterStateVerifier.BestPossAndExtViewZkVerifier(ZK_ADDR, + clusterName, + errStateMap))); + Assert.assertTrue(result, "Cluster verification fails"); + + // reset node "localhost_12918" + participants[0].setTransition(null); + String hostName = "localhost_12918"; + String instanceUrl = "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/instances/" + hostName; + + Map paramMap = new HashMap(); + paramMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.resetInstance); + TestHelixAdminScenariosRest.assertSuccessPostOperation(instanceUrl, paramMap, false); + + result = + ClusterStateVerifier.verifyByZkCallback((new ClusterStateVerifier.BestPossAndExtViewZkVerifier(ZK_ADDR, + clusterName))); + Assert.assertTrue(result, "Cluster verification fails"); + + // clean up + // wait for all zk callbacks done + Thread.sleep(1000); +// adminThread.stop(); + controller.syncStop(); + for (int i = 0; i < 5; i++) + { + participants[i].syncStop(); + } + + System.out.println("END " + clusterName + " at " + + new Date(System.currentTimeMillis())); + } +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetPartitionState.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetPartitionState.java b/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetPartitionState.java new file mode 100644 index 0000000..5715668 --- /dev/null +++ b/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetPartitionState.java @@ -0,0 +1,213 @@ +/** + * Copyright (C) 2012 LinkedIn Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.helix.tools; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.helix.NotificationContext; +import org.apache.helix.TestHelper; +import org.apache.helix.ZNRecord; +import org.apache.helix.PropertyKey.Builder; +import org.apache.helix.manager.zk.ZKHelixDataAccessor; +import org.apache.helix.manager.zk.ZkBaseDataAccessor; +import org.apache.helix.mock.controller.ClusterController; +import org.apache.helix.mock.storage.MockParticipant; +import org.apache.helix.mock.storage.MockParticipant.ErrTransition; +import org.apache.helix.model.LiveInstance; +import org.apache.helix.model.Message; +import org.apache.helix.tools.ClusterSetup; +import org.apache.helix.tools.ClusterStateVerifier; +import org.apache.helix.webapp.resources.JsonParameters; +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class TestResetPartitionState extends AdminTestBase +{ + String getClusterUrl(String cluster) + { + return "http://localhost:" + ADMIN_PORT + "/clusters" + "/" + cluster; + } + + String getInstanceUrl(String cluster, String instance) + { + return "http://localhost:" + ADMIN_PORT + "/clusters/" + cluster + "/instances/" + instance; + } + + String getResourceUrl(String cluster, String resourceGroup) + { + return "http://localhost:" + ADMIN_PORT + "/clusters/" + cluster + "/resourceGroups/" + resourceGroup; + } + + int _errToOfflineInvoked = 0; + class ErrTransitionWithResetCnt extends ErrTransition + { + public ErrTransitionWithResetCnt(Map> errPartitions) + { + super(errPartitions); + } + + @Override + public void doTransition(Message message, NotificationContext context) + { + super.doTransition(message, context); + String fromState = message.getFromState(); + String toState = message.getToState(); + if (fromState.equals("ERROR") && toState.equals("OFFLINE")) + { + // System.err.println("doReset() invoked"); + _errToOfflineInvoked++; + } + } + } + + @Test() + public void testResetPartitionState() throws Exception + { + String className = TestHelper.getTestClassName(); + String methodName = TestHelper.getTestMethodName(); + String clusterName = className + "_" + methodName; + final int n = 5; + + System.out.println("START " + clusterName + " at " + + new Date(System.currentTimeMillis())); + + TestHelper.setupCluster(clusterName, ZK_ADDR, 12918, // participant port + "localhost", // participant name prefix + "TestDB", // resource name prefix + 1, // resources + 10, // partitions per resource + n, // number of nodes + 3, // replicas + "MasterSlave", + true); // do rebalance + + // start admin thread +// AdminThread adminThread = new AdminThread(ZK_ADDR, _port); +// adminThread.start(); + + + // start controller + ClusterController controller = + new ClusterController(clusterName, "controller_0", ZK_ADDR); + controller.syncStart(); + + Map> errPartitions = new HashMap>() + { + { + put("SLAVE-MASTER", TestHelper.setOf("TestDB0_4")); + put("OFFLINE-SLAVE", TestHelper.setOf("TestDB0_8")); + } + }; + + // start mock participants + MockParticipant[] participants = new MockParticipant[n]; + for (int i = 0; i < n; i++) + { + String instanceName = "localhost_" + (12918 + i); + + if (i == 0) + { + participants[i] = + new MockParticipant(clusterName, + instanceName, + ZK_ADDR, + new ErrTransition(errPartitions)); + } + else + { + participants[i] = new MockParticipant(clusterName, instanceName, ZK_ADDR); + } + participants[i].syncStart(); + } + + // verify cluster + Map> errStateMap = + new HashMap>(); + errStateMap.put("TestDB0", new HashMap()); + errStateMap.get("TestDB0").put("TestDB0_4", "localhost_12918"); + errStateMap.get("TestDB0").put("TestDB0_8", "localhost_12918"); + boolean result = + ClusterStateVerifier.verifyByZkCallback((new ClusterStateVerifier.BestPossAndExtViewZkVerifier(ZK_ADDR, + clusterName, + errStateMap))); + Assert.assertTrue(result, "Cluster verification fails"); + + + // reset a non-exist partition, should throw exception + String hostName = "localhost_12918"; + String instanceUrl = getInstanceUrl(clusterName, hostName); + + Map paramMap = new HashMap(); + paramMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.resetPartition); + paramMap.put(JsonParameters.PARTITION, "TestDB0_nonExist"); + paramMap.put(JsonParameters.RESOURCE, "TestDB0"); + System.out.println("IGNORABLE exception: test reset non-exist partition"); + TestHelixAdminScenariosRest.assertSuccessPostOperation(instanceUrl, paramMap, true); + + + // reset one error partition + errPartitions.clear(); // remove("SLAVE-MASTER"); + participants[0].setTransition(new ErrTransitionWithResetCnt(errPartitions)); + clearStatusUpdate(clusterName, "localhost_12918", "TestDB0", "TestDB0_4"); + _errToOfflineInvoked = 0; + + paramMap.put(JsonParameters.PARTITION, "TestDB0_4 TestDB0_8"); + TestHelixAdminScenariosRest.assertSuccessPostOperation(instanceUrl, paramMap, false); + + Thread.sleep(400); // wait reset to be done + System.out.println("IGNORABLE exception: test reset non-error partition"); + TestHelixAdminScenariosRest.assertSuccessPostOperation(instanceUrl, paramMap, true); + + result = + ClusterStateVerifier.verifyByZkCallback(new ClusterStateVerifier.BestPossAndExtViewZkVerifier(ZK_ADDR, + clusterName)); + Assert.assertTrue(result); + Assert.assertEquals(_errToOfflineInvoked, 2, "reset() should be invoked 2 times"); + + + // clean up + // wait for all zk callbacks done + Thread.sleep(1000); +// adminThread.stop(); + controller.syncStop(); + for (int i = 0; i < 5; i++) + { + participants[i].syncStop(); + } + + System.out.println("END " + clusterName + " at " + + new Date(System.currentTimeMillis())); + } + + private void clearStatusUpdate(String clusterName, String instance, String resource, + String partition) + { + // clear status update for error partition so verify() will not fail on old + // errors + ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_gZkClient)); + Builder keyBuilder = accessor.keyBuilder(); + + LiveInstance liveInstance = accessor.getProperty(keyBuilder.liveInstance(instance)); + accessor.removeProperty(keyBuilder.stateTransitionStatus(instance, liveInstance.getSessionId(), resource, partition)); + + } + + // TODO: throw exception in reset() +} http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetResource.java ---------------------------------------------------------------------- diff --git a/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetResource.java b/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetResource.java new file mode 100644 index 0000000..e434279 --- /dev/null +++ b/helix-admin-webapp/src/test/java/org/apache/helix/tools/TestResetResource.java @@ -0,0 +1,120 @@ +package org.apache.helix.tools; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.helix.TestHelper; +import org.apache.helix.mock.controller.ClusterController; +import org.apache.helix.mock.storage.MockParticipant; +import org.apache.helix.mock.storage.MockParticipant.ErrTransition; +import org.apache.helix.tools.ClusterSetup; +import org.apache.helix.tools.ClusterStateVerifier; +import org.apache.helix.webapp.resources.JsonParameters; +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class TestResetResource extends AdminTestBase +{ + @Test + public void testResetNode() throws Exception + { + String className = TestHelper.getTestClassName(); + String methodName = TestHelper.getTestMethodName(); + String clusterName = className + "_" + methodName; + final int n = 5; + + System.out.println("START " + clusterName + " at " + + new Date(System.currentTimeMillis())); + + TestHelper.setupCluster(clusterName, ZK_ADDR, 12918, // participant port + "localhost", // participant name prefix + "TestDB", // resource name prefix + 1, // resources + 10, // partitions per resource + n, // number of nodes + 3, // replicas + "MasterSlave", + true); // do rebalance + + // start admin thread +// AdminThread adminThread = new AdminThread(ZK_ADDR, _port); +// adminThread.start(); + + // start controller + ClusterController controller = + new ClusterController(clusterName, "controller_0", ZK_ADDR); + controller.syncStart(); + + Map> errPartitions = new HashMap>() + { + { + put("SLAVE-MASTER", TestHelper.setOf("TestDB0_4")); + put("OFFLINE-SLAVE", TestHelper.setOf("TestDB0_8")); + } + }; + + // start mock participants + MockParticipant[] participants = new MockParticipant[n]; + for (int i = 0; i < n; i++) + { + String instanceName = "localhost_" + (12918 + i); + + if (i == 0) + { + participants[i] = + new MockParticipant(clusterName, + instanceName, + ZK_ADDR, + new ErrTransition(errPartitions)); + } + else + { + participants[i] = new MockParticipant(clusterName, instanceName, ZK_ADDR); + } + participants[i].syncStart(); + } + + // verify cluster + Map> errStateMap = + new HashMap>(); + errStateMap.put("TestDB0", new HashMap()); + errStateMap.get("TestDB0").put("TestDB0_4", "localhost_12918"); + errStateMap.get("TestDB0").put("TestDB0_8", "localhost_12918"); + boolean result = + ClusterStateVerifier.verifyByZkCallback((new ClusterStateVerifier.BestPossAndExtViewZkVerifier(ZK_ADDR, + clusterName, + errStateMap))); + Assert.assertTrue(result, "Cluster verification fails"); + + // reset resource "TestDB0" + participants[0].setTransition(null); + String resourceName = "TestDB0"; + String resourceUrl = "http://localhost:" + ADMIN_PORT + "/clusters/" + clusterName + "/resourceGroups/" + resourceName; + + Map paramMap = new HashMap(); + paramMap.put(JsonParameters.MANAGEMENT_COMMAND, ClusterSetup.resetResource); + TestHelixAdminScenariosRest.assertSuccessPostOperation(resourceUrl, paramMap, false); + + result = + ClusterStateVerifier.verifyByZkCallback((new ClusterStateVerifier.BestPossAndExtViewZkVerifier(ZK_ADDR, + clusterName))); + Assert.assertTrue(result, "Cluster verification fails"); + + // clean up + // wait for all zk callbacks done + Thread.sleep(1000); +// adminThread.stop(); + controller.syncStop(); + for (int i = 0; i < 5; i++) + { + participants[i].syncStop(); + } + + System.out.println("END " + clusterName + " at " + + new Date(System.currentTimeMillis())); + + } +}