Package org.apache.helix.tools

Source Code of org.apache.helix.tools.ClusterSetup

package org.apache.helix.tools;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.
*/

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.helix.ConfigScope;
import org.apache.helix.ConfigScopeBuilder;
import org.apache.helix.HelixAdmin;
import org.apache.helix.HelixException;
import org.apache.helix.ZNRecord;
import org.apache.helix.HelixConstants.StateModelToken;
import org.apache.helix.PropertyKey.Builder;
import org.apache.helix.manager.zk.ZKHelixAdmin;
import org.apache.helix.manager.zk.ZKHelixDataAccessor;
import org.apache.helix.manager.zk.ZNRecordSerializer;
import org.apache.helix.manager.zk.ZkBaseDataAccessor;
import org.apache.helix.manager.zk.ZkClient;
import org.apache.helix.model.ExternalView;
import org.apache.helix.model.IdealState;
import org.apache.helix.model.InstanceConfig;
import org.apache.helix.model.LiveInstance;
import org.apache.helix.model.StateModelDefinition;
import org.apache.helix.model.IdealState.IdealStateModeProperty;
import org.apache.helix.util.ZKClientPool;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;


public class ClusterSetup
{
  private static Logger logger = Logger.getLogger(ClusterSetup.class);
  public static final String zkServerAddress = "zkSvr";

  // List info about the cluster / DB/ Instances
  public static final String listClusters = "listClusters";
  public static final String listResources = "listResources";
  public static final String listInstances = "listInstances";

  // Add, drop, and rebalance
  public static final String addCluster = "addCluster";
  public static final String activateCluster = "activateCluster";
  public static final String dropCluster = "dropCluster";
  public static final String dropResource = "dropResource";
  public static final String addInstance = "addNode";
  public static final String addResource = "addResource";
  public static final String addStateModelDef = "addStateModelDef";
  public static final String addIdealState = "addIdealState";
  public static final String swapInstance = "swapInstance";
  public static final String dropInstance = "dropNode";
  public static final String rebalance = "rebalance";
  public static final String expandCluster = "expandCluster";
  public static final String expandResource = "expandResource";
  public static final String mode = "mode";
  public static final String bucketSize = "bucketSize";
  public static final String resourceKeyPrefix = "key";
  public static final String addResourceProperty = "addResourceProperty";
  public static final String removeResourceProperty = "removeResourceProperty";

  // Query info (TBD in V2)
  public static final String listClusterInfo = "listClusterInfo";
  public static final String listInstanceInfo = "listInstanceInfo";
  public static final String listResourceInfo = "listResourceInfo";
  public static final String listPartitionInfo = "listPartitionInfo";
  public static final String listStateModels = "listStateModels";
  public static final String listStateModel = "listStateModel";

  // enable/disable/reset instances/cluster/resource/partition
  public static final String enableInstance = "enableInstance";
  public static final String enablePartition = "enablePartition";
  public static final String enableCluster = "enableCluster";
  public static final String resetPartition = "resetPartition";
  public static final String resetInstance = "resetInstance";
  public static final String resetResource = "resetResource";

  // help
  public static final String help = "help";

  // stats/alerts
  public static final String addStat = "addStat";
  public static final String addAlert = "addAlert";
  public static final String dropStat = "dropStat";
  public static final String dropAlert = "dropAlert";

  // get/set configs
  public static final String getConfig = "getConfig";
  public static final String setConfig = "setConfig";
  public static final String removeConfig = "removeConfig";

  static Logger _logger = Logger.getLogger(ClusterSetup.class);
  String _zkServerAddress;
  ZkClient _zkClient;
  HelixAdmin _admin;

  public ClusterSetup(String zkServerAddress)
  {
    _zkServerAddress = zkServerAddress;
    _zkClient = ZKClientPool.getZkClient(_zkServerAddress);
    _admin = new ZKHelixAdmin(_zkClient);
  }

  public ClusterSetup(ZkClient zkClient)
  {
    _zkServerAddress = zkClient.getServers();
    _zkClient = zkClient;
    _admin = new ZKHelixAdmin(_zkClient);
  }

  public void addCluster(String clusterName, boolean overwritePrevious)
  {
    _admin.addCluster(clusterName, overwritePrevious);

    StateModelConfigGenerator generator = new StateModelConfigGenerator();
    addStateModelDef(clusterName,
                     "MasterSlave",
                     new StateModelDefinition(generator.generateConfigForMasterSlave()));
    addStateModelDef(clusterName,
                     "LeaderStandby",
                     new StateModelDefinition(generator.generateConfigForLeaderStandby()));
    addStateModelDef(clusterName,
                     "StorageSchemata",
                     new StateModelDefinition(generator.generateConfigForStorageSchemata()));
    addStateModelDef(clusterName,
                     "OnlineOffline",
                     new StateModelDefinition(generator.generateConfigForOnlineOffline()));
  }

  public void activateCluster(String clusterName, String grandCluster, boolean enable)
  {
    if (enable)
    {
      _admin.addClusterToGrandCluster(clusterName, grandCluster);
    }
    else
    {
      _admin.dropResource(grandCluster, clusterName);
    }
  }

  public void deleteCluster(String clusterName)
  {
    _admin.dropCluster(clusterName);
  }

  public void addInstancesToCluster(String clusterName, String[] InstanceInfoArray)
  {
    for (String InstanceInfo : InstanceInfoArray)
    {
      // the storage Instance info must be hostname:port format.
      if (InstanceInfo.length() > 0)
      {
        addInstanceToCluster(clusterName, InstanceInfo);
      }
    }
  }

  public void addInstanceToCluster(String clusterName, String InstanceAddress)
  {
    // InstanceAddress must be in host:port format
    int lastPos = InstanceAddress.lastIndexOf("_");
    if (lastPos <= 0)
    {
      lastPos = InstanceAddress.lastIndexOf(":");
    }
    if (lastPos <= 0)
    {
      String error = "Invalid storage Instance info format: " + InstanceAddress;
      _logger.warn(error);
      throw new HelixException(error);
    }
    String host = InstanceAddress.substring(0, lastPos);
    String portStr = InstanceAddress.substring(lastPos + 1);
    int port = Integer.parseInt(portStr);
    addInstanceToCluster(clusterName, host, port);
  }

  public void addInstanceToCluster(String clusterName, String host, int port)
  {
    String instanceId = host + "_" + port;
    InstanceConfig config = new InstanceConfig(instanceId);
    config.setHostName(host);
    config.setPort(Integer.toString(port));
    config.setInstanceEnabled(true);
    _admin.addInstance(clusterName, config);
  }

  public void dropInstancesFromCluster(String clusterName, String[] InstanceInfoArray)
  {
    for (String InstanceInfo : InstanceInfoArray)
    {
      // the storage Instance info must be hostname:port format.
      if (InstanceInfo.length() > 0)
      {
        dropInstanceFromCluster(clusterName, InstanceInfo);
      }
    }
  }

  public void dropInstanceFromCluster(String clusterName, String InstanceAddress)
  {
    // InstanceAddress must be in host:port format
    int lastPos = InstanceAddress.lastIndexOf("_");
    if (lastPos <= 0)
    {
      lastPos = InstanceAddress.lastIndexOf(":");
    }
    if (lastPos <= 0)
    {
      String error = "Invalid storage Instance info format: " + InstanceAddress;
      _logger.warn(error);
      throw new HelixException(error);
    }
    String host = InstanceAddress.substring(0, lastPos);
    String portStr = InstanceAddress.substring(lastPos + 1);
    int port = Integer.parseInt(portStr);
    dropInstanceFromCluster(clusterName, host, port);
  }

  public void dropInstanceFromCluster(String clusterName, String host, int port)
  {
    String instanceId = host + "_" + port;

    ZKHelixDataAccessor accessor =
        new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor<ZNRecord>(_zkClient));
    Builder keyBuilder = accessor.keyBuilder();

    // ensure node is stopped
    LiveInstance liveInstance = accessor.getProperty(keyBuilder.liveInstance(instanceId));
    if (liveInstance != null)
    {
      throw new HelixException("Can't drop " + instanceId + ", please stop " + instanceId
          + " before drop it");
    }

    InstanceConfig config = accessor.getProperty(keyBuilder.instanceConfig(instanceId));
    if (config == null)
    {
      String error = "Node " + instanceId + " does not exist, cannot drop";
      _logger.warn(error);
      throw new HelixException(error);
    }

    // ensure node is disabled, otherwise fail
    if (config.getInstanceEnabled())
    {
      String error = "Node " + instanceId + " is enabled, cannot drop";
      _logger.warn(error);
      throw new HelixException(error);
    }
    _admin.dropInstance(clusterName, config);
  }

  public void swapInstance(String clusterName,
                           String oldInstanceName,
                           String newInstanceName)
  {
    ZKHelixDataAccessor accessor =
        new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_zkClient));
    Builder keyBuilder = accessor.keyBuilder();

    InstanceConfig oldConfig =
        accessor.getProperty(keyBuilder.instanceConfig(oldInstanceName));
    if (oldConfig == null)
    {
      String error = "Old instance " + oldInstanceName + " does not exist, cannot swap";
      _logger.warn(error);
      throw new HelixException(error);
    }

    InstanceConfig newConfig =
        accessor.getProperty(keyBuilder.instanceConfig(newInstanceName));
    if (newConfig == null)
    {
      String error = "New instance " + newInstanceName + " does not exist, cannot swap";
      _logger.warn(error);
      throw new HelixException(error);
    }

    // ensure old instance is disabled, otherwise fail
    if (oldConfig.getInstanceEnabled())
    {
      String error =
          "Old instance " + oldInstanceName
              + " is enabled, it need to be disabled and turned off";
      _logger.warn(error);
      throw new HelixException(error);
    }
    // ensure old instance is down, otherwise fail
    List<String> liveInstanceNames =
        accessor.getChildNames(accessor.keyBuilder().liveInstances());

    if (liveInstanceNames.contains(oldInstanceName))
    {
      String error =
          "Old instance " + oldInstanceName
              + " is still on, it need to be disabled and turned off";
      _logger.warn(error);
      throw new HelixException(error);
    }

    dropInstanceFromCluster(clusterName, oldInstanceName);

    List<IdealState> existingIdealStates =
        accessor.getChildValues(accessor.keyBuilder().idealStates());
    for (IdealState idealState : existingIdealStates)
    {
      swapInstanceInIdealState(idealState, oldInstanceName, newInstanceName);
      accessor.setProperty(accessor.keyBuilder()
                                   .idealStates(idealState.getResourceName()), idealState);
    }
  }

  void swapInstanceInIdealState(IdealState idealState,
                                String oldInstance,
                                String newInstance)
  {
    for (String partition : idealState.getRecord().getMapFields().keySet())
    {
      Map<String, String> valMap = idealState.getRecord().getMapField(partition);
      if (valMap.containsKey(oldInstance))
      {
        valMap.put(newInstance, valMap.get(oldInstance));
        valMap.remove(oldInstance);
      }
    }

    for (String partition : idealState.getRecord().getListFields().keySet())
    {
      List<String> valList = idealState.getRecord().getListField(partition);
      for (int i = 0; i < valList.size(); i++)
      {
        if (valList.get(i).equals(oldInstance))
        {
          valList.remove(i);
          valList.add(i, newInstance);
        }
      }
    }
  }

  public HelixAdmin getClusterManagementTool()
  {
    return _admin;
  }

  public void addStateModelDef(String clusterName,
                               String stateModelDef,
                               StateModelDefinition record)
  {
    _admin.addStateModelDef(clusterName, stateModelDef, record);
  }

  public void addResourceToCluster(String clusterName,
                                   String resourceName,
                                   int numResources,
                                   String stateModelRef)
  {
    addResourceToCluster(clusterName,
                         resourceName,
                         numResources,
                         stateModelRef,
                         IdealStateModeProperty.AUTO.toString());
  }

  public void addResourceToCluster(String clusterName,
                                   String resourceName,
                                   int numResources,
                                   String stateModelRef,
                                   String idealStateMode)
  {
    _admin.addResource(clusterName,
                       resourceName,
                       numResources,
                       stateModelRef,
                       idealStateMode);
  }

  public void addResourceToCluster(String clusterName,
                                   String resourceName,
                                   int numResources,
                                   String stateModelRef,
                                   String idealStateMode,
                                   int bucketSize)
  {
    _admin.addResource(clusterName,
                       resourceName,
                       numResources,
                       stateModelRef,
                       idealStateMode,
                       bucketSize);
  }

  public void dropResourceFromCluster(String clusterName, String resourceName)
  {
    _admin.dropResource(clusterName, resourceName);
  }

  // TODO: remove this. has moved to ZkHelixAdmin
  public void rebalanceStorageCluster(String clusterName, String resourceName, int replica)
  {
    rebalanceStorageCluster(clusterName, resourceName, replica, resourceName);
  }

  public void reblanceResource(String clusterName, String resourceName, int replica)
  {
    rebalanceStorageCluster(clusterName, resourceName, replica, resourceName);
  }
  public void expandResource(String clusterName, String resourceName)
  {
    IdealState idealState = _admin.getResourceIdealState(clusterName, resourceName);
    if (idealState.getIdealStateMode() == IdealStateModeProperty.AUTO_REBALANCE
        || idealState.getIdealStateMode() == IdealStateModeProperty.CUSTOMIZED)
    {
      _logger.info("Skipping idealState " + idealState.getResourceName() + " "
          + idealState.getIdealStateMode());
      return;
    }
    boolean anyLiveInstance = false;
    for (List<String> list : idealState.getRecord().getListFields().values())
    {
      if (list.contains(StateModelToken.ANY_LIVEINSTANCE.toString()))
      {
        _logger.info("Skipping idealState " + idealState.getResourceName()
            + " with ANY_LIVEINSTANCE");
        anyLiveInstance = true;
        continue;
      }
    }
    if (anyLiveInstance)
    {
      return;
    }
    try
    {
      int replica = Integer.parseInt(idealState.getReplicas());
    }
    catch (Exception e)
    {
      _logger.error("", e);
      return;
    }
    if (idealState.getRecord().getListFields().size() == 0)
    {
      _logger.warn("Resource " + resourceName + " not balanced, skip");
      return;
    }
    balanceIdealState(clusterName, idealState);
  }

  public void expandCluster(String clusterName)
  {
    List<String> resources = _admin.getResourcesInCluster(clusterName);
    for (String resourceName : resources)
    {
      expandResource(clusterName, resourceName);
    }
  }

 

  public void balanceIdealState(String clusterName, IdealState idealState)
  {
    // The new instances are added into the cluster already. So we need to find out the
    // instances that
    // already have partitions assigned to them.
    List<String> instanceNames = _admin.getInstancesInCluster(clusterName);
    rebalanceResource(clusterName, idealState, instanceNames);

  }

  private void rebalanceResource(String clusterName,
      IdealState idealState, List<String> instanceNames)
  {
     _admin.rebalance(clusterName, idealState, instanceNames);
  }

  public void rebalanceStorageCluster(String clusterName,
                                      String resourceName,
                                      int replica,
                                      String keyPrefix)
  {
    _admin.rebalance(clusterName, resourceName, replica, keyPrefix);
  }

  /**
   * setConfig
   *
   * @param scopeStr
   *          : scope=value, ... where scope=CLUSTER, RESOURCE, PARTICIPANT, PARTITION
   * @param properitesStr
   *          : key=value, ... which represents a Map<String, String>
   */
  public void setConfig(String scopesStr, String propertiesStr)
  {
    ConfigScope scope = new ConfigScopeBuilder().build(scopesStr);

    // parse properties
    String[] properties = propertiesStr.split("[\\s,]");
    Map<String, String> propertiesMap = new TreeMap<String, String>();
    for (String property : properties)
    {
      int idx = property.indexOf('=');
      if (idx == -1)
      {
        logger.error("Invalid property string: " + property);
        continue;
      }

      String key = property.substring(0, idx);
      String value = property.substring(idx + 1);
      propertiesMap.put(key, value);
    }
    logger.debug("propertiesMap: " + propertiesMap);

    _admin.setConfig(scope, propertiesMap);
  }

  public void removeConfig(String scopesStr, String keysStr)
  {
    ConfigScope scope = new ConfigScopeBuilder().build(scopesStr);

    // parse keys
    String[] keys = keysStr.split("[\\s,]");
    Set<String> keysSet = new HashSet<String>(Arrays.asList(keys));

    _admin.removeConfig(scope, keysSet);
  }

  public String getConfig(String scopesStr, String keysStr)
  {
    ConfigScope scope = new ConfigScopeBuilder().build(scopesStr);

    // parse keys
    String[] keys = keysStr.split("[\\s,]");
    Set<String> keysSet = new HashSet<String>(Arrays.asList(keys));

    Map<String, String> propertiesMap = _admin.getConfig(scope, keysSet);
    StringBuffer sb = new StringBuffer();
    for (String key : keys)
    {
      if (propertiesMap.containsKey(key))
      {
        if (sb.length() > 0)
        {
          sb.append("," + key + "=" + propertiesMap.get(key));
        }
        else
        {
          // sb.length()==0 means the first key=value
          sb.append(key + "=" + propertiesMap.get(key));
        }
      }
      else
      {
        logger.error("Config doesn't exist for key: " + key);
      }
    }

    System.out.println(sb.toString());
    return sb.toString();
  }

  /**
   * Sets up a cluster with 6 Instances[localhost:8900 to localhost:8905], 1
   * resource[EspressoDB] with a replication factor of 3
   *
   * @param clusterName
   */
  public void setupTestCluster(String clusterName)
  {
    addCluster(clusterName, true);
    String storageInstanceInfoArray[] = new String[6];
    for (int i = 0; i < storageInstanceInfoArray.length; i++)
    {
      storageInstanceInfoArray[i] = "localhost:" + (8900 + i);
    }
    addInstancesToCluster(clusterName, storageInstanceInfoArray);
    addResourceToCluster(clusterName, "TestDB", 10, "MasterSlave");
    rebalanceStorageCluster(clusterName, "TestDB", 3);
  }

  public static void printUsage(Options cliOptions)
  {
    HelpFormatter helpFormatter = new HelpFormatter();
    helpFormatter.setWidth(1000);
    helpFormatter.printHelp("java " + ClusterSetup.class.getName(), cliOptions);
  }

  @SuppressWarnings("static-access")
  private static Options constructCommandLineOptions()
  {
    Option helpOption =
        OptionBuilder.withLongOpt(help)
                     .withDescription("Prints command-line options info")
                     .create();

    Option zkServerOption =
        OptionBuilder.withLongOpt(zkServerAddress)
                     .withDescription("Provide zookeeper address")
                     .create();
    zkServerOption.setArgs(1);
    zkServerOption.setRequired(true);
    zkServerOption.setArgName("ZookeeperServerAddress(Required)");

    Option listClustersOption =
        OptionBuilder.withLongOpt(listClusters)
                     .withDescription("List existing clusters")
                     .create();
    listClustersOption.setArgs(0);
    listClustersOption.setRequired(false);

    Option listResourceOption =
        OptionBuilder.withLongOpt(listResources)
                     .withDescription("List resources hosted in a cluster")
                     .create();
    listResourceOption.setArgs(1);
    listResourceOption.setRequired(false);
    listResourceOption.setArgName("clusterName");

    Option listInstancesOption =
        OptionBuilder.withLongOpt(listInstances)
                     .withDescription("List Instances in a cluster")
                     .create();
    listInstancesOption.setArgs(1);
    listInstancesOption.setRequired(false);
    listInstancesOption.setArgName("clusterName");

    Option addClusterOption =
        OptionBuilder.withLongOpt(addCluster)
                     .withDescription("Add a new cluster")
                     .create();
    addClusterOption.setArgs(1);
    addClusterOption.setRequired(false);
    addClusterOption.setArgName("clusterName");

    Option activateClusterOption =
        OptionBuilder.withLongOpt(activateCluster)
                     .withDescription("Enable/disable a cluster in distributed controller mode")
                     .create();
    activateClusterOption.setArgs(3);
    activateClusterOption.setRequired(false);
    activateClusterOption.setArgName("clusterName grandCluster true/false");

    Option deleteClusterOption =
        OptionBuilder.withLongOpt(dropCluster)
                     .withDescription("Delete a cluster")
                     .create();
    deleteClusterOption.setArgs(1);
    deleteClusterOption.setRequired(false);
    deleteClusterOption.setArgName("clusterName");

    Option addInstanceOption =
        OptionBuilder.withLongOpt(addInstance)
                     .withDescription("Add a new Instance to a cluster")
                     .create();
    addInstanceOption.setArgs(2);
    addInstanceOption.setRequired(false);
    addInstanceOption.setArgName("clusterName InstanceAddress(host:port)");

    Option addResourceOption =
        OptionBuilder.withLongOpt(addResource)
                     .withDescription("Add a resource to a cluster")
                     .create();
    addResourceOption.setArgs(4);
    addResourceOption.setRequired(false);
    addResourceOption.setArgName("clusterName resourceName partitionNum stateModelRef <-mode modeValue>");

    Option expandResourceOption =
        OptionBuilder.withLongOpt(expandResource)
                     .withDescription("Expand resource to additional nodes")
                     .create();
    expandResourceOption.setArgs(2);
    expandResourceOption.setRequired(false);
    expandResourceOption.setArgName("clusterName resourceName");

    Option expandClusterOption =
        OptionBuilder.withLongOpt(expandCluster)
                     .withDescription("Expand a cluster and all the resources")
                     .create();
    expandClusterOption.setArgs(1);
    expandClusterOption.setRequired(false);
    expandClusterOption.setArgName("clusterName");

    Option resourceModeOption =
        OptionBuilder.withLongOpt(mode)
                     .withDescription("Specify resource mode, used with addResourceGroup command")
                     .create();
    resourceModeOption.setArgs(1);
    resourceModeOption.setRequired(false);
    resourceModeOption.setArgName("IdealState mode");

    Option resourceBucketSizeOption =
        OptionBuilder.withLongOpt(bucketSize)
                     .withDescription("Specify size of a bucket, used with addResourceGroup command")
                     .create();
    resourceBucketSizeOption.setArgs(1);
    resourceBucketSizeOption.setRequired(false);
    resourceBucketSizeOption.setArgName("Size of a bucket for a resource");

    Option resourceKeyOption =
        OptionBuilder.withLongOpt(resourceKeyPrefix)
                     .withDescription("Specify resource key prefix, used with rebalance command")
                     .create();
    resourceKeyOption.setArgs(1);
    resourceKeyOption.setRequired(false);
    resourceKeyOption.setArgName("Resource key prefix");

    Option addStateModelDefOption =
        OptionBuilder.withLongOpt(addStateModelDef)
                     .withDescription("Add a State model to a cluster")
                     .create();
    addStateModelDefOption.setArgs(2);
    addStateModelDefOption.setRequired(false);
    addStateModelDefOption.setArgName("clusterName <filename>");

    Option addIdealStateOption =
        OptionBuilder.withLongOpt(addIdealState)
                     .withDescription("Add a State model to a cluster")
                     .create();
    addIdealStateOption.setArgs(3);
    addIdealStateOption.setRequired(false);
    addIdealStateOption.setArgName("clusterName resourceName <filename>");

    Option dropInstanceOption =
        OptionBuilder.withLongOpt(dropInstance)
                     .withDescription("Drop an existing Instance from a cluster")
                     .create();
    dropInstanceOption.setArgs(2);
    dropInstanceOption.setRequired(false);
    dropInstanceOption.setArgName("clusterName InstanceAddress(host:port)");

    Option swapInstanceOption =
        OptionBuilder.withLongOpt(swapInstance)
                     .withDescription("Swap an old instance from a cluster with a new instance")
                     .create();
    swapInstanceOption.setArgs(3);
    swapInstanceOption.setRequired(false);
    swapInstanceOption.setArgName("clusterName oldInstance newInstance");

    Option dropResourceOption =
        OptionBuilder.withLongOpt(dropResource)
                     .withDescription("Drop an existing resource from a cluster")
                     .create();
    dropResourceOption.setArgs(2);
    dropResourceOption.setRequired(false);
    dropResourceOption.setArgName("clusterName resourceName");

    Option rebalanceOption =
        OptionBuilder.withLongOpt(rebalance)
                     .withDescription("Rebalance a resource in a cluster")
                     .create();
    rebalanceOption.setArgs(3);
    rebalanceOption.setRequired(false);
    rebalanceOption.setArgName("clusterName resourceName replicas");

    Option instanceInfoOption =
        OptionBuilder.withLongOpt(listInstanceInfo)
                     .withDescription("Query info of a Instance in a cluster")
                     .create();
    instanceInfoOption.setArgs(2);
    instanceInfoOption.setRequired(false);
    instanceInfoOption.setArgName("clusterName InstanceName");

    Option clusterInfoOption =
        OptionBuilder.withLongOpt(listClusterInfo)
                     .withDescription("Query info of a cluster")
                     .create();
    clusterInfoOption.setArgs(1);
    clusterInfoOption.setRequired(false);
    clusterInfoOption.setArgName("clusterName");

    Option resourceInfoOption =
        OptionBuilder.withLongOpt(listResourceInfo)
                     .withDescription("Query info of a resource")
                     .create();
    resourceInfoOption.setArgs(2);
    resourceInfoOption.setRequired(false);
    resourceInfoOption.setArgName("clusterName resourceName");

    Option addResourcePropertyOption =
        OptionBuilder.withLongOpt(addResourceProperty)
                     .withDescription("Add a resource property")
                     .create();
    addResourcePropertyOption.setArgs(4);
    addResourcePropertyOption.setRequired(false);
    addResourcePropertyOption.setArgName("clusterName resourceName propertyName propertyValue");

    Option removeResourcePropertyOption =
        OptionBuilder.withLongOpt(removeResourceProperty)
                     .withDescription("Remove a resource property")
                     .create();
    removeResourcePropertyOption.setArgs(3);
    removeResourcePropertyOption.setRequired(false);
    removeResourcePropertyOption.setArgName("clusterName resourceName propertyName");

    Option partitionInfoOption =
        OptionBuilder.withLongOpt(listPartitionInfo)
                     .withDescription("Query info of a partition")
                     .create();
    partitionInfoOption.setArgs(3);
    partitionInfoOption.setRequired(false);
    partitionInfoOption.setArgName("clusterName resourceName partitionName");

    Option enableInstanceOption =
        OptionBuilder.withLongOpt(enableInstance)
                     .withDescription("Enable/disable a Instance")
                     .create();
    enableInstanceOption.setArgs(3);
    enableInstanceOption.setRequired(false);
    enableInstanceOption.setArgName("clusterName InstanceName true/false");

    Option enablePartitionOption =
        OptionBuilder.hasArgs()
                     .withLongOpt(enablePartition)
                     .withDescription("Enable/disable partitions")
                     .create();
    enablePartitionOption.setRequired(false);
    enablePartitionOption.setArgName("true/false clusterName instanceName resourceName partitionName1...");

    Option enableClusterOption =
        OptionBuilder.withLongOpt(enableCluster)
                     .withDescription("pause/resume the controller of a cluster")
                     .create();
    enableClusterOption.setArgs(2);
    enableClusterOption.setRequired(false);
    enableClusterOption.setArgName("clusterName true/false");

    Option resetPartitionOption =
        OptionBuilder.withLongOpt(resetPartition)
                     .withDescription("Reset a partition in error state")
                     .create();
    resetPartitionOption.setArgs(4);
    resetPartitionOption.setRequired(false);
    resetPartitionOption.setArgName("clusterName instanceName resourceName partitionName");

    Option resetInstanceOption =
        OptionBuilder.withLongOpt(resetInstance)
                     .withDescription("Reset all partitions in error state for an instance")
                     .create();
    resetInstanceOption.setArgs(2);
    resetInstanceOption.setRequired(false);
    resetInstanceOption.setArgName("clusterName instanceName");

    Option resetResourceOption =
        OptionBuilder.withLongOpt(resetResource)
                     .withDescription("Reset all partitions in error state for a resource")
                     .create();
    resetResourceOption.setArgs(2);
    resetResourceOption.setRequired(false);
    resetResourceOption.setArgName("clusterName resourceName");

    Option listStateModelsOption =
        OptionBuilder.withLongOpt(listStateModels)
                     .withDescription("Query info of state models in a cluster")
                     .create();
    listStateModelsOption.setArgs(1);
    listStateModelsOption.setRequired(false);
    listStateModelsOption.setArgName("clusterName");

    Option listStateModelOption =
        OptionBuilder.withLongOpt(listStateModel)
                     .withDescription("Query info of a state model in a cluster")
                     .create();
    listStateModelOption.setArgs(2);
    listStateModelOption.setRequired(false);
    listStateModelOption.setArgName("clusterName stateModelName");

    Option addStatOption =
        OptionBuilder.withLongOpt(addStat)
                     .withDescription("Add a persistent stat")
                     .create();
    addStatOption.setArgs(2);
    addStatOption.setRequired(false);
    addStatOption.setArgName("clusterName statName");
    Option addAlertOption =
        OptionBuilder.withLongOpt(addAlert).withDescription("Add an alert").create();
    addAlertOption.setArgs(2);
    addAlertOption.setRequired(false);
    addAlertOption.setArgName("clusterName alertName");

    Option dropStatOption =
        OptionBuilder.withLongOpt(dropStat)
                     .withDescription("Drop a persistent stat")
                     .create();
    dropStatOption.setArgs(2);
    dropStatOption.setRequired(false);
    dropStatOption.setArgName("clusterName statName");
    Option dropAlertOption =
        OptionBuilder.withLongOpt(dropAlert).withDescription("Drop an alert").create();
    dropAlertOption.setArgs(2);
    dropAlertOption.setRequired(false);
    dropAlertOption.setArgName("clusterName alertName");

    // set/get configs option
    Option setConfOption =
        OptionBuilder.withLongOpt(setConfig).withDescription("Set a config").create();
    setConfOption.setArgs(2);
    setConfOption.setRequired(false);
    setConfOption.setArgName("ConfigScope(e.g. CLUSTER=cluster,RESOURCE=rc,...) KeyValueMap(e.g. k1=v1,k2=v2,...)");

    Option getConfOption =
        OptionBuilder.withLongOpt(getConfig).withDescription("Get a config").create();
    getConfOption.setArgs(2);
    getConfOption.setRequired(false);
    getConfOption.setArgName("ConfigScope(e.g. CLUSTER=cluster,RESOURCE=rc,...) KeySet(e.g. k1,k2,...)");

    OptionGroup group = new OptionGroup();
    group.setRequired(true);
    group.addOption(rebalanceOption);
    group.addOption(addResourceOption);
    group.addOption(resourceModeOption);
    group.addOption(resourceBucketSizeOption);
    group.addOption(expandResourceOption);
    group.addOption(expandClusterOption);
    group.addOption(resourceKeyOption);
    group.addOption(addClusterOption);
    group.addOption(activateClusterOption);
    group.addOption(deleteClusterOption);
    group.addOption(addInstanceOption);
    group.addOption(listInstancesOption);
    group.addOption(listResourceOption);
    group.addOption(listClustersOption);
    group.addOption(addIdealStateOption);
    group.addOption(rebalanceOption);
    group.addOption(dropInstanceOption);
    group.addOption(swapInstanceOption);
    group.addOption(dropResourceOption);
    group.addOption(instanceInfoOption);
    group.addOption(clusterInfoOption);
    group.addOption(resourceInfoOption);
    group.addOption(partitionInfoOption);
    group.addOption(enableInstanceOption);
    group.addOption(enablePartitionOption);
    group.addOption(enableClusterOption);
    group.addOption(resetPartitionOption);
    group.addOption(resetInstanceOption);
    group.addOption(resetResourceOption);
    group.addOption(addStateModelDefOption);
    group.addOption(listStateModelsOption);
    group.addOption(listStateModelOption);
    group.addOption(addStatOption);
    group.addOption(addAlertOption);
    group.addOption(dropStatOption);
    group.addOption(dropAlertOption);
    group.addOption(setConfOption);
    group.addOption(getConfOption);
    group.addOption(addResourcePropertyOption);
    group.addOption(removeResourcePropertyOption);

    Options options = new Options();
    options.addOption(helpOption);
    options.addOption(zkServerOption);
    options.addOptionGroup(group);
    return options;
  }
 
  // TODO: remove this. has moved to ZkHelixAdmin
  private static byte[] readFile(String filePath) throws IOException
  {
    File file = new File(filePath);

    int size = (int) file.length();
    byte[] bytes = new byte[size];
    DataInputStream dis = new DataInputStream(new FileInputStream(file));
    int read = 0;
    int numRead = 0;
    while (read < bytes.length
        && (numRead = dis.read(bytes, read, bytes.length - read)) >= 0)
    {
      read = read + numRead;
    }
    return bytes;
  }

  public static int processCommandLineArgs(String[] cliArgs) throws Exception
  {
    CommandLineParser cliParser = new GnuParser();
    Options cliOptions = constructCommandLineOptions();
    CommandLine cmd = null;

    try
    {
      cmd = cliParser.parse(cliOptions, cliArgs);
    }
    catch (ParseException pe)
    {
      System.err.println("CommandLineClient: failed to parse command-line options: "
          + pe.toString());
      printUsage(cliOptions);
      System.exit(1);
    }

    ClusterSetup setupTool = new ClusterSetup(cmd.getOptionValue(zkServerAddress));

    if (cmd.hasOption(addCluster))
    {
      String clusterName = cmd.getOptionValue(addCluster);
      setupTool.addCluster(clusterName, false);
      return 0;
    }

    if (cmd.hasOption(activateCluster))
    {
      String clusterName = cmd.getOptionValues(activateCluster)[0];
      String grandCluster = cmd.getOptionValues(activateCluster)[1];
      boolean enable = Boolean.parseBoolean(cmd.getOptionValues(activateCluster)[2]);
      setupTool.activateCluster(clusterName, grandCluster, enable);
      return 0;
    }

    if (cmd.hasOption(dropCluster))
    {
      String clusterName = cmd.getOptionValue(dropCluster);
      setupTool.deleteCluster(clusterName);
      return 0;
    }

    if (cmd.hasOption(addInstance))
    {
      String clusterName = cmd.getOptionValues(addInstance)[0];
      String InstanceAddressInfo = cmd.getOptionValues(addInstance)[1];
      String[] InstanceAddresses = InstanceAddressInfo.split(";");
      setupTool.addInstancesToCluster(clusterName, InstanceAddresses);
      return 0;
    }

    if (cmd.hasOption(addResource))
    {
      String clusterName = cmd.getOptionValues(addResource)[0];
      String resourceName = cmd.getOptionValues(addResource)[1];
      int partitions = Integer.parseInt(cmd.getOptionValues(addResource)[2]);
      String stateModelRef = cmd.getOptionValues(addResource)[3];
      String modeValue = IdealStateModeProperty.AUTO.toString();
      if (cmd.hasOption(mode))
      {
        modeValue = cmd.getOptionValues(mode)[0];
      }

      int bucketSizeVal = 0;
      if (cmd.hasOption(bucketSize))
      {
        bucketSizeVal = Integer.parseInt(cmd.getOptionValues(bucketSize)[0]);
      }

      setupTool.addResourceToCluster(clusterName,
                                     resourceName,
                                     partitions,
                                     stateModelRef,
                                     modeValue,
                                     bucketSizeVal);
      return 0;
    }

    if (cmd.hasOption(rebalance))
    {
      String clusterName = cmd.getOptionValues(rebalance)[0];
      String resourceName = cmd.getOptionValues(rebalance)[1];
      int replicas = Integer.parseInt(cmd.getOptionValues(rebalance)[2]);
      if (cmd.hasOption(resourceKeyPrefix))
      {
        setupTool.rebalanceStorageCluster(clusterName,
                                          resourceName,
                                          replicas,
                                          cmd.getOptionValue(resourceKeyPrefix));
        return 0;
      }
      setupTool.rebalanceStorageCluster(clusterName, resourceName, replicas);
      return 0;
    }

    if (cmd.hasOption(expandCluster))
    {
      String clusterName = cmd.getOptionValues(expandCluster)[0];

      setupTool.expandCluster(clusterName);
      return 0;
    }

    if (cmd.hasOption(expandResource))
    {
      String clusterName = cmd.getOptionValues(expandResource)[0];
      String resourceName = cmd.getOptionValues(expandResource)[1];
      setupTool.expandResource(clusterName, resourceName);
      return 0;
    }

    if (cmd.hasOption(dropInstance))
    {
      String clusterName = cmd.getOptionValues(dropInstance)[0];
      String InstanceAddressInfo = cmd.getOptionValues(dropInstance)[1];
      String[] InstanceAddresses = InstanceAddressInfo.split(";");
      setupTool.dropInstancesFromCluster(clusterName, InstanceAddresses);
      return 0;
    }

    if (cmd.hasOption(listClusters))
    {
      List<String> clusters = setupTool.getClusterManagementTool().getClusters();

      System.out.println("Existing clusters:");
      for (String cluster : clusters)
      {
        System.out.println(cluster);
      }
      return 0;
    }

    if (cmd.hasOption(listResources))
    {
      String clusterName = cmd.getOptionValue(listResources);
      List<String> resourceNames =
          setupTool.getClusterManagementTool().getResourcesInCluster(clusterName);

      System.out.println("Existing resources in cluster " + clusterName + ":");
      for (String resourceName : resourceNames)
      {
        System.out.println(resourceName);
      }
      return 0;
    }
    else if (cmd.hasOption(listClusterInfo))
    {
      String clusterName = cmd.getOptionValue(listClusterInfo);
      List<String> resourceNames =
          setupTool.getClusterManagementTool().getResourcesInCluster(clusterName);
      List<String> Instances =
          setupTool.getClusterManagementTool().getInstancesInCluster(clusterName);

      System.out.println("Existing resources in cluster " + clusterName + ":");
      for (String resourceName : resourceNames)
      {
        System.out.println(resourceName);
      }

      System.out.println("Instances in cluster " + clusterName + ":");
      for (String InstanceName : Instances)
      {
        System.out.println(InstanceName);
      }
      return 0;
    }
    else if (cmd.hasOption(listInstances))
    {
      String clusterName = cmd.getOptionValue(listInstances);
      List<String> Instances =
          setupTool.getClusterManagementTool().getInstancesInCluster(clusterName);

      System.out.println("Instances in cluster " + clusterName + ":");
      for (String InstanceName : Instances)
      {
        System.out.println(InstanceName);
      }
      return 0;
    }
    else if (cmd.hasOption(listInstanceInfo))
    {
      String clusterName = cmd.getOptionValues(listInstanceInfo)[0];
      String instanceName = cmd.getOptionValues(listInstanceInfo)[1];
      InstanceConfig config =
          setupTool.getClusterManagementTool().getInstanceConfig(clusterName,
                                                                 instanceName);

      String result = new String(new ZNRecordSerializer().serialize(config.getRecord()));
      System.out.println("InstanceConfig: " + result);
      return 0;
    }
    else if (cmd.hasOption(listResourceInfo))
    {
      // print out partition number, db name and replication number
      // Also the ideal states and current states
      String clusterName = cmd.getOptionValues(listResourceInfo)[0];
      String resourceName = cmd.getOptionValues(listResourceInfo)[1];
      IdealState idealState =
          setupTool.getClusterManagementTool().getResourceIdealState(clusterName,
                                                                     resourceName);
      ExternalView externalView =
          setupTool.getClusterManagementTool().getResourceExternalView(clusterName,
                                                                       resourceName);

      if (idealState != null)
      {
        System.out.println("IdealState for " + resourceName + ":");
        System.out.println(new String(new ZNRecordSerializer().serialize(idealState.getRecord())));
      }
      else
      {
        System.out.println("No idealState for " + resourceName);
      }

      System.out.println();

      if (externalView != null)
      {
        System.out.println("ExternalView for " + resourceName + ":");
        System.out.println(new String(new ZNRecordSerializer().serialize(externalView.getRecord())));
      }
      else
      {
        System.out.println("No externalView for " + resourceName);
      }
      return 0;

    }
    else if (cmd.hasOption(listPartitionInfo))
    {
      // print out where the partition master / slaves locates
      String clusterName = cmd.getOptionValues(listPartitionInfo)[0];
      String resourceName = cmd.getOptionValues(listPartitionInfo)[1];
      String partitionName = cmd.getOptionValues(listPartitionInfo)[2];
      IdealState idealState =
          setupTool.getClusterManagementTool().getResourceIdealState(clusterName,
                                                                     resourceName);
      ExternalView externalView =
          setupTool.getClusterManagementTool().getResourceExternalView(clusterName,
                                                                       resourceName);

      if (idealState != null)
      {
        ZNRecord partInfo = new ZNRecord(resourceName + "/" + partitionName);
        ZNRecord idealStateRec = idealState.getRecord();
        partInfo.setSimpleFields(idealStateRec.getSimpleFields());
        if (idealStateRec.getMapField(partitionName) != null)
        {
          partInfo.setMapField(partitionName, idealStateRec.getMapField(partitionName));
        }
        if (idealStateRec.getListField(partitionName) != null)
        {
          partInfo.setListField(partitionName, idealStateRec.getListField(partitionName));
        }
        System.out.println("IdealState for " + resourceName + "/" + partitionName + ":");
        System.out.println(new String(new ZNRecordSerializer().serialize(partInfo)));
      }
      else
      {
        System.out.println("No idealState for " + resourceName + "/" + partitionName);
      }

      System.out.println();

      if (externalView != null)
      {
        ZNRecord partInfo = new ZNRecord(resourceName + "/" + partitionName);
        ZNRecord extViewRec = externalView.getRecord();
        partInfo.setSimpleFields(extViewRec.getSimpleFields());
        if (extViewRec.getMapField(partitionName) != null)
        {
          partInfo.setMapField(partitionName, extViewRec.getMapField(partitionName));
        }
        if (extViewRec.getListField(partitionName) != null)
        {
          partInfo.setListField(partitionName, extViewRec.getListField(partitionName));
        }

        System.out.println("ExternalView for " + resourceName + "/" + partitionName + ":");
        System.out.println(new String(new ZNRecordSerializer().serialize(partInfo)));
      }
      else
      {
        System.out.println("No externalView for " + resourceName + "/" + partitionName);
      }
      return 0;

    }
    else if (cmd.hasOption(enableInstance))
    {
      String clusterName = cmd.getOptionValues(enableInstance)[0];
      String instanceName = cmd.getOptionValues(enableInstance)[1];
      if (instanceName.contains(":"))
      {
        instanceName = instanceName.replaceAll(":", "_");
      }
      boolean enabled =
          Boolean.parseBoolean(cmd.getOptionValues(enableInstance)[2].toLowerCase());

      setupTool.getClusterManagementTool().enableInstance(clusterName,
                                                          instanceName,
                                                          enabled);
      return 0;
    }
    else if (cmd.hasOption(enablePartition))
    {
      String[] args = cmd.getOptionValues(enablePartition);

      boolean enabled = Boolean.parseBoolean(args[0].toLowerCase());
      String clusterName = args[1];
      String instanceName = args[2];
      String resourceName = args[3];

      List<String> partitionNames =
          Arrays.asList(Arrays.copyOfRange(args, 4, args.length));
      setupTool.getClusterManagementTool().enablePartition(enabled,
                                                           clusterName,
                                                           instanceName,
                                                           resourceName,
                                                           partitionNames);
      return 0;
    }
    else if (cmd.hasOption(resetPartition))
    {
      String[] args = cmd.getOptionValues(resetPartition);

      String clusterName = args[0];
      String instanceName = args[1];
      String resourceName = args[2];
      List<String> partitionNames =
          Arrays.asList(Arrays.copyOfRange(args, 3, args.length));

      setupTool.getClusterManagementTool().resetPartition(clusterName,
                                                          instanceName,
                                                          resourceName,
                                                          partitionNames);
      return 0;
    }
    else if (cmd.hasOption(resetInstance))
    {
      String[] args = cmd.getOptionValues(resetInstance);

      String clusterName = args[0];
      List<String> instanceNames =
          Arrays.asList(Arrays.copyOfRange(args, 1, args.length));

      setupTool.getClusterManagementTool().resetInstance(clusterName, instanceNames);
      return 0;
    }
    else if (cmd.hasOption(resetResource))
    {
      String[] args = cmd.getOptionValues(resetResource);

      String clusterName = args[0];
      List<String> resourceNames =
          Arrays.asList(Arrays.copyOfRange(args, 1, args.length));

      setupTool.getClusterManagementTool().resetResource(clusterName, resourceNames);
      return 0;
    }
    else if (cmd.hasOption(enableCluster))
    {
      String[] params = cmd.getOptionValues(enableCluster);
      String clusterName = params[0];
      boolean enabled = Boolean.parseBoolean(params[1].toLowerCase());
      setupTool.getClusterManagementTool().enableCluster(clusterName, enabled);

      return 0;
    }
    else if (cmd.hasOption(listStateModels))
    {
      String clusterName = cmd.getOptionValues(listStateModels)[0];

      List<String> stateModels =
          setupTool.getClusterManagementTool().getStateModelDefs(clusterName);

      System.out.println("Existing state models:");
      for (String stateModel : stateModels)
      {
        System.out.println(stateModel);
      }
      return 0;
    }
    else if (cmd.hasOption(listStateModel))
    {
      String clusterName = cmd.getOptionValues(listStateModel)[0];
      String stateModel = cmd.getOptionValues(listStateModel)[1];
      StateModelDefinition stateModelDef =
          setupTool.getClusterManagementTool().getStateModelDef(clusterName, stateModel);
      String result =
          new String(new ZNRecordSerializer().serialize(stateModelDef.getRecord()));
      System.out.println("StateModelDefinition: " + result);
      return 0;
    }
    else if (cmd.hasOption(addStateModelDef))
    {
      String clusterName = cmd.getOptionValues(addStateModelDef)[0];
      String stateModelFile = cmd.getOptionValues(addStateModelDef)[1];

      ZNRecord stateModelRecord =
          (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(stateModelFile)));
      if (stateModelRecord.getId() == null || stateModelRecord.getId().length() == 0)
      {
        throw new IllegalArgumentException("ZNRecord for state model definition must have an id");
      }
      setupTool.getClusterManagementTool()
               .addStateModelDef(clusterName,
                                 stateModelRecord.getId(),
                                 new StateModelDefinition(stateModelRecord));
      return 0;
    }
    else if (cmd.hasOption(addIdealState))
    {
      String clusterName = cmd.getOptionValues(addIdealState)[0];
      String resourceName = cmd.getOptionValues(addIdealState)[1];
      String idealStateFile = cmd.getOptionValues(addIdealState)[2];

      setupTool.addIdealState(clusterName, resourceName, idealStateFile);
      return 0;
    }
    else if (cmd.hasOption(addStat))
    {
      String clusterName = cmd.getOptionValues(addStat)[0];
      String statName = cmd.getOptionValues(addStat)[1];

      setupTool.getClusterManagementTool().addStat(clusterName, statName);
    }
    else if (cmd.hasOption(addAlert))
    {
      String clusterName = cmd.getOptionValues(addAlert)[0];
      String alertName = cmd.getOptionValues(addAlert)[1];

      setupTool.getClusterManagementTool().addAlert(clusterName, alertName);
    }
    else if (cmd.hasOption(dropStat))
    {
      String clusterName = cmd.getOptionValues(dropStat)[0];
      String statName = cmd.getOptionValues(dropStat)[1];

      setupTool.getClusterManagementTool().dropStat(clusterName, statName);
    }
    else if (cmd.hasOption(dropAlert))
    {
      String clusterName = cmd.getOptionValues(dropAlert)[0];
      String alertName = cmd.getOptionValues(dropAlert)[1];

      setupTool.getClusterManagementTool().dropAlert(clusterName, alertName);
    }
    else if (cmd.hasOption(dropResource))
    {
      String clusterName = cmd.getOptionValues(dropResource)[0];
      String resourceName = cmd.getOptionValues(dropResource)[1];

      setupTool.getClusterManagementTool().dropResource(clusterName, resourceName);
    }
    else if (cmd.hasOption(swapInstance))
    {
      String clusterName = cmd.getOptionValues(swapInstance)[0];
      String oldInstanceName = cmd.getOptionValues(swapInstance)[1];
      String newInstanceName = cmd.getOptionValues(swapInstance)[2];

      setupTool.swapInstance(clusterName, oldInstanceName, newInstanceName);
    }
    else if (cmd.hasOption(setConfig))
    {
      String scopeStr = cmd.getOptionValues(setConfig)[0];
      String propertiesStr = cmd.getOptionValues(setConfig)[1];
      setupTool.setConfig(scopeStr, propertiesStr);
    }
    else if (cmd.hasOption(getConfig))
    {
      String scopeStr = cmd.getOptionValues(getConfig)[0];
      String keysStr = cmd.getOptionValues(getConfig)[1];
      setupTool.getConfig(scopeStr, keysStr);
    }
    else if (cmd.hasOption(help))
    {
      printUsage(cliOptions);
      return 0;
    }
    else if (cmd.hasOption(addResourceProperty))
    {
      String clusterName = cmd.getOptionValues(addResourceProperty)[0];
      String resourceName = cmd.getOptionValues(addResourceProperty)[1];
      String propertyKey = cmd.getOptionValues(addResourceProperty)[2];
      String propertyVal = cmd.getOptionValues(addResourceProperty)[3];

      setupTool.addResourceProperty(clusterName, resourceName, propertyKey, propertyVal);
      return 0;
    }
    else if (cmd.hasOption(removeResourceProperty))
    {
      String clusterName = cmd.getOptionValues(removeResourceProperty)[0];
      String resourceName = cmd.getOptionValues(removeResourceProperty)[1];
      String propertyKey = cmd.getOptionValues(removeResourceProperty)[2];

      setupTool.removeResourceProperty(clusterName, resourceName, propertyKey);
      return 0;
    }
    return 0;
  }

  // TODO: remove this. has moved to ZkHelixAdmin
  public void addIdealState(String clusterName, String resourceName, String idealStateFile) throws IOException
  {
    ZNRecord idealStateRecord =
        (ZNRecord) (new ZNRecordSerializer().deserialize(readFile(idealStateFile)));
    if (idealStateRecord.getId() == null
        || !idealStateRecord.getId().equals(resourceName))
    {
      throw new IllegalArgumentException("ideal state must have same id as resource name");
    }
    _admin.setResourceIdealState(clusterName,
                                 resourceName,
                                 new IdealState(idealStateRecord));
  }

  public void addResourceProperty(String clusterName,
                                  String resourceName,
                                  String propertyKey,
                                  String propertyVal)
  {
    IdealState idealState = _admin.getResourceIdealState(clusterName, resourceName);
    if (idealState == null)
    {
      throw new HelixException("Resource: " + resourceName + " has NOT been added yet");
    }
    idealState.getRecord().setSimpleField(propertyKey, propertyVal);
    _admin.setResourceIdealState(clusterName, resourceName, idealState);
  }

  public void removeResourceProperty(String clusterName,
                                     String resourceName,
                                     String propertyKey)
  {
    IdealState idealState = _admin.getResourceIdealState(clusterName, resourceName);
    if (idealState == null)
    {
      throw new HelixException("Resource: " + resourceName + " has NOT been added yet");
    }
    idealState.getRecord().getSimpleFields().remove(propertyKey);
    _admin.setResourceIdealState(clusterName, resourceName, idealState);
  }

  /**
   * @param args
   * @throws Exception
   * @throws JsonMappingException
   * @throws JsonGenerationException
   */
  public static void main(String[] args) throws Exception
  {
    // debug
    // System.out.println("args(" + args.length + "): " + Arrays.asList(args));

    if (args.length == 1 && args[0].equals("setup-test-cluster"))
    {
      System.out.println("By default setting up ");
      new ClusterSetup("localhost:2181").setupTestCluster("storage-integration-cluster");
      new ClusterSetup("localhost:2181").setupTestCluster("relay-integration-cluster");
      System.exit(0);
    }

    int ret = processCommandLineArgs(args);
    System.exit(ret);
  }
}
TOP

Related Classes of org.apache.helix.tools.ClusterSetup

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.