/* * 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. */ package org.apache.solr.handler; import java.io.File; import java.io.IOException; import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.embedded.JettySolrRunner; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.SolrPing; import org.apache.solr.client.solrj.response.SolrPingResponse; import org.apache.solr.cloud.MiniSolrCloudCluster; import org.apache.solr.common.SolrException; import org.apache.solr.common.util.NamedList; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.SolrQueryResponse; import org.junit.Before; import org.junit.BeforeClass; public class PingRequestHandlerTest extends SolrTestCaseJ4 { protected int NUM_SERVERS = 5; protected int NUM_SHARDS = 2; protected int REPLICATION_FACTOR = 2; private final String fileName = this.getClass().getName() + ".server-enabled"; private File healthcheckFile = null; private PingRequestHandler handler = null; @BeforeClass public static void beforeClass() throws Exception { initCore("solrconfig.xml", "schema.xml"); } @Before public void before() throws IOException { File tmpDir = initCoreDataDir; // by default, use relative file in dataDir healthcheckFile = new File(tmpDir, fileName); String fileNameParam = fileName; // sometimes randomly use an absolute File path instead if (random().nextBoolean()) { healthcheckFile = new File(tmpDir, fileName); fileNameParam = healthcheckFile.getAbsolutePath(); } if (healthcheckFile.exists()) FileUtils.forceDelete(healthcheckFile); handler = new PingRequestHandler(); NamedList initParams = new NamedList(); initParams.add(PingRequestHandler.HEALTHCHECK_FILE_PARAM, fileNameParam); handler.init(initParams); handler.inform(h.getCore()); } public void testPingWithNoHealthCheck() throws Exception { // for this test, we don't want any healthcheck file configured at all handler = new PingRequestHandler(); handler.init(new NamedList()); handler.inform(h.getCore()); SolrQueryResponse rsp = null; rsp = makeRequest(handler, req()); assertEquals("OK", rsp.getValues().get("status")); rsp = makeRequest(handler, req("action","ping")); assertEquals("OK", rsp.getValues().get("status")); } public void testEnablingServer() throws Exception { assertTrue(!healthcheckFile.exists()); // first make sure that ping responds back that the service is disabled SolrQueryResponse sqr = makeRequest(handler, req()); SolrException se = (SolrException) sqr.getException(); assertEquals( "Response should have been replaced with a 503 SolrException.", se.code(), SolrException.ErrorCode.SERVICE_UNAVAILABLE.code); // now enable makeRequest(handler, req("action", "enable")); assertTrue(healthcheckFile.exists()); assertNotNull(FileUtils.readFileToString(healthcheckFile, "UTF-8")); // now verify that the handler response with success SolrQueryResponse rsp = makeRequest(handler, req()); assertEquals("OK", rsp.getValues().get("status")); // enable when already enabled shouldn't cause any problems makeRequest(handler, req("action", "enable")); assertTrue(healthcheckFile.exists()); } public void testDisablingServer() throws Exception { assertTrue(! healthcheckFile.exists()); healthcheckFile.createNewFile(); // first make sure that ping responds back that the service is enabled SolrQueryResponse rsp = makeRequest(handler, req()); assertEquals("OK", rsp.getValues().get("status")); // now disable makeRequest(handler, req("action", "disable")); assertFalse(healthcheckFile.exists()); // now make sure that ping responds back that the service is disabled SolrQueryResponse sqr = makeRequest(handler, req()); SolrException se = (SolrException) sqr.getException(); assertEquals( "Response should have been replaced with a 503 SolrException.", se.code(), SolrException.ErrorCode.SERVICE_UNAVAILABLE.code); // disable when already disabled shouldn't cause any problems makeRequest(handler, req("action", "disable")); assertFalse(healthcheckFile.exists()); } public void testGettingStatus() throws Exception { SolrQueryResponse rsp = null; handler.handleEnable(true); rsp = makeRequest(handler, req("action", "status")); assertEquals("enabled", rsp.getValues().get("status")); handler.handleEnable(false); rsp = makeRequest(handler, req("action", "status")); assertEquals("disabled", rsp.getValues().get("status")); } public void testBadActionRaisesException() throws Exception { try { SolrQueryResponse rsp = makeRequest(handler, req("action", "badaction")); fail("Should have thrown a SolrException for the bad action"); } catch (SolrException se){ assertEquals(SolrException.ErrorCode.BAD_REQUEST.code,se.code()); } } public void testPingInClusterWithNoHealthCheck() throws Exception { MiniSolrCloudCluster miniCluster = new MiniSolrCloudCluster(NUM_SERVERS, createTempDir(), buildJettyConfig("/solr")); final CloudSolrClient cloudSolrClient = miniCluster.getSolrClient(); try { assertNotNull(miniCluster.getZkServer()); List<JettySolrRunner> jettys = miniCluster.getJettySolrRunners(); assertEquals(NUM_SERVERS, jettys.size()); for (JettySolrRunner jetty : jettys) { assertTrue(jetty.isRunning()); } // create collection String collectionName = "testSolrCloudCollection"; String configName = "solrCloudCollectionConfig"; miniCluster.uploadConfigSet(SolrTestCaseJ4.TEST_PATH().resolve("collection1").resolve("conf"), configName); CollectionAdminRequest.createCollection(collectionName, configName, NUM_SHARDS, REPLICATION_FACTOR) .process(miniCluster.getSolrClient()); // Send distributed and non-distributed ping query SolrPingWithDistrib reqDistrib = new SolrPingWithDistrib(); reqDistrib.setDistrib(true); SolrPingResponse rsp = reqDistrib.process(cloudSolrClient, collectionName); assertEquals(0, rsp.getStatus()); assertTrue(rsp.getResponseHeader().getBooleanArg(("zkConnected"))); SolrPing reqNonDistrib = new SolrPing(); rsp = reqNonDistrib.process(cloudSolrClient, collectionName); assertEquals(0, rsp.getStatus()); assertTrue(rsp.getResponseHeader().getBooleanArg(("zkConnected"))); } finally { miniCluster.shutdown(); } } /** * Helper Method: Executes the request against the handler, returns * the response, and closes the request. */ private SolrQueryResponse makeRequest(PingRequestHandler handler, SolrQueryRequest req) throws Exception { SolrQueryResponse rsp = new SolrQueryResponse(); try { handler.handleRequestBody(req, rsp); } finally { req.close(); } return rsp; } static class SolrPingWithDistrib extends SolrPing { public SolrPing setDistrib(boolean distrib) { getParams().add("distrib", distrib ? "true" : "false"); return this; } } }