private void testNodesUsedByCreate() throws Exception {
    // we can use this client because we just want base url
    final String baseUrl = getBaseUrl((HttpSolrServer) clients.get(0));

    ModifiableSolrParams params = new ModifiableSolrParams();
    params.set("action", CollectionAction.CREATE.toString());

    params.set("numShards", 2);
    params.set(REPLICATION_FACTOR, 2);
    String collectionName = "nodes_used_collection";

    params.set("name", collectionName);

    if (secondConfigSet) {
      params.set("collection.configName", "conf1");
    }

    QueryRequest request = new QueryRequest(params);
    request.setPath("/admin/collections");
    createNewSolrServer("", baseUrl).request(request);

    List<Integer> numShardsNumReplicaList = new ArrayList<Integer>();
    numShardsNumReplicaList.add(2);
    numShardsNumReplicaList.add(2);
    checkForCollection("nodes_used_collection", numShardsNumReplicaList, null);

    List<String> createNodeList = new ArrayList<String>();

    Set<String> liveNodes = cloudClient.getZkStateReader().getClusterState().getLiveNodes();

    for (String node : liveNodes) {
      createNodeList.add(node);
    }

    DocCollection col =
        cloudClient.getZkStateReader().getClusterState().getCollection("nodes_used_collection");
    Collection<Slice> slices = col.getSlices();
    for (Slice slice : slices) {
      Collection<Replica> replicas = slice.getReplicas();
      for (Replica replica : replicas) {
        createNodeList.remove(replica.getNodeName());
      }
    }
    assertEquals(createNodeList.toString(), 1, createNodeList.size());
  }
  private void deletePartiallyCreatedCollection() throws Exception {
    final String baseUrl = getBaseUrl((HttpSolrServer) clients.get(0));
    String collectionName = "halfdeletedcollection";
    Create createCmd = new Create();
    createCmd.setCoreName("halfdeletedcollection_shard1_replica1");
    createCmd.setCollection(collectionName);
    String dataDir =
        SolrTestCaseJ4.dataDir.getAbsolutePath()
            + File.separator
            + System.currentTimeMillis()
            + "halfcollection"
            + "_hdn";
    createCmd.setDataDir(dataDir);
    createCmd.setNumShards(2);
    if (secondConfigSet) {
      createCmd.setCollectionConfigName("conf1");
    }
    createNewSolrServer("", baseUrl).request(createCmd);

    ModifiableSolrParams params = new ModifiableSolrParams();
    params.set("action", CollectionAction.DELETE.toString());
    params.set("name", collectionName);
    QueryRequest request = new QueryRequest(params);
    request.setPath("/admin/collections");

    NamedList<Object> resp = createNewSolrServer("", baseUrl).request(request);

    checkForMissingCollection(collectionName);

    // now creating that collection should work
    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.CREATE.toString());
    params.set("name", collectionName);
    params.set("numShards", 2);
    request = new QueryRequest(params);
    request.setPath("/admin/collections");
    if (secondConfigSet) {
      params.set("collection.configName", "conf1");
    }
    resp = createNewSolrServer("", baseUrl).request(request);
  }
  private void testCollectionsAPI() throws Exception {

    // TODO: fragile - because we dont pass collection.confName, it will only
    // find a default if a conf set with a name matching the collection name is found, or
    // if there is only one conf set. That and the fact that other tests run first in this
    // env make this pretty fragile

    // create new collections rapid fire
    Map<String, List<Integer>> collectionInfos = new HashMap<String, List<Integer>>();
    int cnt = random().nextInt(TEST_NIGHTLY ? 6 : 3) + 1;

    for (int i = 0; i < cnt; i++) {
      int numShards = _TestUtil.nextInt(random(), 0, shardCount) + 1;
      int replicationFactor = _TestUtil.nextInt(random(), 0, 3) + 1;
      int maxShardsPerNode =
          (((numShards * replicationFactor)
                  / getCommonCloudSolrServer()
                      .getZkStateReader()
                      .getClusterState()
                      .getLiveNodes()
                      .size()))
              + 1;

      CloudSolrServer client = null;
      try {
        if (i == 0) {
          // Test if we can create a collection through CloudSolrServer where
          // you havnt set default-collection
          // This is nice because you want to be able to create you first
          // collection using CloudSolrServer, and in such case there is
          // nothing reasonable to set as default-collection
          client = createCloudClient(null);
        } else if (i == 1) {
          // Test if we can create a collection through CloudSolrServer where
          // you have set default-collection to a non-existing collection
          // This is nice because you want to be able to create you first
          // collection using CloudSolrServer, and in such case there is
          // nothing reasonable to set as default-collection, but you might want
          // to use the same CloudSolrServer throughout the entire
          // lifetime of your client-application, so it is nice to be able to
          // set a default-collection on this CloudSolrServer once and for all
          // and use this CloudSolrServer to create the collection
          client = createCloudClient("awholynewcollection_" + i);
        }
        if (secondConfigSet) {
          createCollection(
              collectionInfos,
              "awholynewcollection_" + i,
              numShards,
              replicationFactor,
              maxShardsPerNode,
              client,
              null,
              "conf2");
        } else {
          createCollection(
              collectionInfos,
              "awholynewcollection_" + i,
              numShards,
              replicationFactor,
              maxShardsPerNode,
              client,
              null);
        }
      } finally {
        if (client != null) client.shutdown();
      }
    }

    Set<Entry<String, List<Integer>>> collectionInfosEntrySet = collectionInfos.entrySet();
    for (Entry<String, List<Integer>> entry : collectionInfosEntrySet) {
      String collection = entry.getKey();
      List<Integer> list = entry.getValue();
      checkForCollection(collection, list, null);

      String url = getUrlFromZk(collection);

      HttpSolrServer collectionClient = new HttpSolrServer(url);

      // poll for a second - it can take a moment before we are ready to serve
      waitForNon403or404or503(collectionClient);
    }

    // sometimes we restart one of the jetty nodes
    if (random().nextBoolean()) {
      JettySolrRunner jetty = jettys.get(random().nextInt(jettys.size()));
      ChaosMonkey.stop(jetty);
      ChaosMonkey.start(jetty);

      for (Entry<String, List<Integer>> entry : collectionInfosEntrySet) {
        String collection = entry.getKey();
        List<Integer> list = entry.getValue();
        checkForCollection(collection, list, null);

        String url = getUrlFromZk(collection);

        HttpSolrServer collectionClient = new HttpSolrServer(url);

        // poll for a second - it can take a moment before we are ready to serve
        waitForNon403or404or503(collectionClient);
      }
    }

    // sometimes we restart zookeeper
    if (random().nextBoolean()) {
      zkServer.shutdown();
      zkServer = new ZkTestServer(zkServer.getZkDir(), zkServer.getPort());
      zkServer.run();
    }

    // sometimes we cause a connection loss - sometimes it will hit the overseer
    if (random().nextBoolean()) {
      JettySolrRunner jetty = jettys.get(random().nextInt(jettys.size()));
      ChaosMonkey.causeConnectionLoss(jetty);
    }

    ZkStateReader zkStateReader = getCommonCloudSolrServer().getZkStateReader();
    for (int j = 0; j < cnt; j++) {
      waitForRecoveriesToFinish("awholynewcollection_" + j, zkStateReader, false);

      if (secondConfigSet) {
        // let's see if they are using the second config set
        byte[] data =
            zkStateReader
                .getZkClient()
                .getData(
                    ZkStateReader.COLLECTIONS_ZKNODE + "/" + "awholynewcollection_" + j,
                    null,
                    null,
                    true);
        assertNotNull(data);
        ZkNodeProps props = ZkNodeProps.load(data);
        String configName = props.getStr(ZkController.CONFIGNAME_PROP);
        assertEquals("conf2", configName);
      }
    }

    checkInstanceDirs(jettys.get(0));

    List<String> collectionNameList = new ArrayList<String>();
    collectionNameList.addAll(collectionInfos.keySet());
    String collectionName = collectionNameList.get(random().nextInt(collectionNameList.size()));

    String url = getUrlFromZk(collectionName);

    HttpSolrServer collectionClient = new HttpSolrServer(url);

    // lets try and use the solrj client to index a couple documents
    SolrInputDocument doc1 = getDoc(id, 6, i1, -600, tlong, 600, t1, "humpty dumpy sat on a wall");
    SolrInputDocument doc2 =
        getDoc(id, 7, i1, -600, tlong, 600, t1, "humpty dumpy3 sat on a walls");
    SolrInputDocument doc3 =
        getDoc(id, 8, i1, -600, tlong, 600, t1, "humpty dumpy2 sat on a walled");

    collectionClient.add(doc1);

    collectionClient.add(doc2);

    collectionClient.add(doc3);

    collectionClient.commit();

    assertEquals(3, collectionClient.query(new SolrQuery("*:*")).getResults().getNumFound());

    // lets try a collection reload

    // get core open times
    Map<String, Long> urlToTimeBefore = new HashMap<String, Long>();
    collectStartTimes(collectionName, urlToTimeBefore);
    assertTrue(urlToTimeBefore.size() > 0);
    ModifiableSolrParams params = new ModifiableSolrParams();
    params.set("action", CollectionAction.RELOAD.toString());
    params.set("name", collectionName);
    QueryRequest request = new QueryRequest(params);
    request.setPath("/admin/collections");

    // we can use this client because we just want base url
    final String baseUrl = getBaseUrl((HttpSolrServer) clients.get(0));

    createNewSolrServer("", baseUrl).request(request);

    // reloads make take a short while
    boolean allTimesAreCorrect = waitForReloads(collectionName, urlToTimeBefore);
    assertTrue("some core start times did not change on reload", allTimesAreCorrect);

    waitForRecoveriesToFinish("awholynewcollection_" + (cnt - 1), zkStateReader, false);

    // remove a collection
    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.DELETE.toString());
    params.set("name", collectionName);
    request = new QueryRequest(params);
    request.setPath("/admin/collections");

    createNewSolrServer("", baseUrl).request(request);

    // ensure its out of the state
    checkForMissingCollection(collectionName);

    // collectionNameList.remove(collectionName);

    // remove an unknown collection
    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.DELETE.toString());
    params.set("name", "unknown_collection");
    request = new QueryRequest(params);
    request.setPath("/admin/collections");

    boolean exp = false;
    try {
      createNewSolrServer("", baseUrl).request(request);
    } catch (SolrException e) {
      exp = true;
    }
    assertTrue("Expected exception", exp);

    // create another collection should still work
    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.CREATE.toString());

    params.set("numShards", 1);
    params.set(REPLICATION_FACTOR, 2);
    collectionName = "acollectionafterbaddelete";

    params.set("name", collectionName);
    if (secondConfigSet) {
      params.set("collection.configName", "conf1");
    }
    request = new QueryRequest(params);
    request.setPath("/admin/collections");
    createNewSolrServer("", baseUrl).request(request);

    List<Integer> list = new ArrayList<Integer>(2);
    list.add(1);
    list.add(2);
    checkForCollection(collectionName, list, null);

    url = getUrlFromZk(collectionName);

    collectionClient = new HttpSolrServer(url);

    // poll for a second - it can take a moment before we are ready to serve
    waitForNon403or404or503(collectionClient);

    for (int j = 0; j < cnt; j++) {
      waitForRecoveriesToFinish(collectionName, zkStateReader, false);
    }

    // test maxShardsPerNode
    int numLiveNodes =
        getCommonCloudSolrServer().getZkStateReader().getClusterState().getLiveNodes().size();
    int numShards = (numLiveNodes / 2) + 1;
    int replicationFactor = 2;
    int maxShardsPerNode = 1;
    collectionInfos = new HashMap<String, List<Integer>>();
    CloudSolrServer client = createCloudClient("awholynewcollection_" + cnt);
    try {
      exp = false;
      try {
        createCollection(
            collectionInfos,
            "awholynewcollection_" + cnt,
            numShards,
            replicationFactor,
            maxShardsPerNode,
            client,
            null,
            "conf1");
      } catch (SolrException e) {
        exp = true;
      }
      assertTrue("expected exception", exp);
    } finally {
      client.shutdown();
    }

    // Test createNodeSet
    numLiveNodes =
        getCommonCloudSolrServer().getZkStateReader().getClusterState().getLiveNodes().size();
    List<String> createNodeList = new ArrayList<String>();
    int numOfCreateNodes = numLiveNodes / 2;
    assertFalse(
        "createNodeSet test is pointless with only " + numLiveNodes + " nodes running",
        numOfCreateNodes == 0);
    int i = 0;
    for (String liveNode :
        getCommonCloudSolrServer().getZkStateReader().getClusterState().getLiveNodes()) {
      if (i < numOfCreateNodes) {
        createNodeList.add(liveNode);
        i++;
      } else {
        break;
      }
    }
    maxShardsPerNode = 2;
    numShards = createNodeList.size() * maxShardsPerNode;
    replicationFactor = 1;
    collectionInfos = new HashMap<String, List<Integer>>();
    client = createCloudClient("awholynewcollection_" + (cnt + 1));
    try {
      createCollection(
          collectionInfos,
          "awholynewcollection_" + (cnt + 1),
          numShards,
          replicationFactor,
          maxShardsPerNode,
          client,
          StrUtils.join(createNodeList, ','),
          "conf1");
    } finally {
      client.shutdown();
    }
    checkForCollection(
        collectionInfos.keySet().iterator().next(),
        collectionInfos.entrySet().iterator().next().getValue(),
        createNodeList);

    checkNoTwoShardsUseTheSameIndexDir();
  }
  private void testErrorHandling() throws Exception {
    final String baseUrl = getBaseUrl((HttpSolrServer) clients.get(0));

    // try a bad action
    ModifiableSolrParams params = new ModifiableSolrParams();
    params.set("action", "BADACTION");
    String collectionName = "badactioncollection";
    params.set("name", collectionName);
    params.set("numShards", 2);
    QueryRequest request = new QueryRequest(params);
    request.setPath("/admin/collections");
    boolean gotExp = false;
    NamedList<Object> resp = null;
    try {
      resp = createNewSolrServer("", baseUrl).request(request);
    } catch (SolrException e) {
      gotExp = true;
    }
    assertTrue(gotExp);

    // leave out required param name
    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.CREATE.toString());
    params.set("numShards", 2);
    collectionName = "collection";
    // No Name
    // params.set("name", collectionName);
    if (secondConfigSet) {
      params.set("collection.configName", "conf1");
    }
    request = new QueryRequest(params);
    request.setPath("/admin/collections");
    gotExp = false;
    resp = null;
    try {
      resp = createNewSolrServer("", baseUrl).request(request);
    } catch (SolrException e) {
      gotExp = true;
    }
    assertTrue(gotExp);

    // Too many replicas
    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.CREATE.toString());
    collectionName = "collection";
    params.set("name", collectionName);
    params.set("numShards", 2);
    if (secondConfigSet) {
      params.set("collection.configName", "conf1");
    }
    params.set(REPLICATION_FACTOR, 10);
    request = new QueryRequest(params);
    request.setPath("/admin/collections");
    gotExp = false;
    resp = null;
    try {
      resp = createNewSolrServer("", baseUrl).request(request);
    } catch (SolrException e) {
      gotExp = true;
    }
    assertTrue(gotExp);

    // No numShards should fail
    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.CREATE.toString());
    collectionName = "acollection";
    params.set("name", collectionName);
    params.set(REPLICATION_FACTOR, 10);
    if (secondConfigSet) {
      params.set("collection.configName", "conf1");
    }
    request = new QueryRequest(params);
    request.setPath("/admin/collections");
    gotExp = false;
    resp = null;
    try {
      resp = createNewSolrServer("", baseUrl).request(request);
    } catch (SolrException e) {
      gotExp = true;
    }
    assertTrue(gotExp);

    // 0 numShards should fail
    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.CREATE.toString());
    collectionName = "acollection";
    params.set("name", collectionName);
    params.set(REPLICATION_FACTOR, 10);
    params.set("numShards", 0);
    if (secondConfigSet) {
      params.set("collection.configName", "conf1");
    }
    request = new QueryRequest(params);
    request.setPath("/admin/collections");
    gotExp = false;
    resp = null;
    try {
      resp = createNewSolrServer("", baseUrl).request(request);
    } catch (SolrException e) {
      gotExp = true;
    }
    assertTrue(gotExp);

    // Fail on one node

    // first we make a core with the core name the collections api
    // will try and use - this will cause our mock fail
    Create createCmd = new Create();
    createCmd.setCoreName("halfcollection_shard1_replica1");
    createCmd.setCollection("halfcollectionblocker");
    String dataDir =
        SolrTestCaseJ4.dataDir.getAbsolutePath()
            + File.separator
            + System.currentTimeMillis()
            + "halfcollection"
            + "_3n";
    createCmd.setDataDir(dataDir);
    createCmd.setNumShards(1);
    if (secondConfigSet) {
      createCmd.setCollectionConfigName("conf1");
    }
    createNewSolrServer("", baseUrl).request(createCmd);

    createCmd = new Create();
    createCmd.setCoreName("halfcollection_shard1_replica1");
    createCmd.setCollection("halfcollectionblocker2");
    dataDir =
        SolrTestCaseJ4.dataDir.getAbsolutePath()
            + File.separator
            + System.currentTimeMillis()
            + "halfcollection"
            + "_3n";
    createCmd.setDataDir(dataDir);
    createCmd.setNumShards(1);
    if (secondConfigSet) {
      createCmd.setCollectionConfigName("conf1");
    }
    createNewSolrServer("", getBaseUrl((HttpSolrServer) clients.get(1))).request(createCmd);

    params = new ModifiableSolrParams();
    params.set("action", CollectionAction.CREATE.toString());
    collectionName = "halfcollection";
    params.set("name", collectionName);
    params.set("numShards", 2);
    params.set("wt", "xml");

    if (secondConfigSet) {
      params.set("collection.configName", "conf1");
    }

    String nn1 =
        ((SolrDispatchFilter) jettys.get(0).getDispatchFilter().getFilter())
            .getCores()
            .getZkController()
            .getNodeName();
    String nn2 =
        ((SolrDispatchFilter) jettys.get(1).getDispatchFilter().getFilter())
            .getCores()
            .getZkController()
            .getNodeName();

    params.set(OverseerCollectionProcessor.CREATE_NODE_SET, nn1 + "," + nn2);
    request = new QueryRequest(params);
    request.setPath("/admin/collections");
    gotExp = false;
    resp = createNewSolrServer("", baseUrl).request(request);

    SimpleOrderedMap success = (SimpleOrderedMap) resp.get("success");
    SimpleOrderedMap failure = (SimpleOrderedMap) resp.get("failure");

    assertNotNull(resp.toString(), success);
    assertNotNull(resp.toString(), failure);

    String val1 = success.getVal(0).toString();
    String val2 = failure.getVal(0).toString();
    assertTrue(val1.contains("SolrException") || val2.contains("SolrException"));
  }