diff --git a/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java index 12f9776a9a1..c923fdb3c3e 100644 --- a/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java @@ -18,6 +18,9 @@ package org.apache.solr.handler; import java.io.File; +import java.io.FileWriter; +import java.text.SimpleDateFormat; +import java.util.Date; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; @@ -35,17 +38,70 @@ import org.apache.solr.response.SolrQueryResponse; */ public class PingRequestHandler extends RequestHandlerBase { + + SimpleDateFormat formatRFC3339 = new SimpleDateFormat("yyyy-MM-dd'T'h:m:ss.SZ"); + protected enum ACTIONS {STATUS, ENABLE, DISABLE, PING}; + private String healthcheck = null; + @Override public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { + SolrParams params = req.getParams(); SolrCore core = req.getCore(); // Check if the service is available - String healthcheck = core.getSolrConfig().get("admin/healthcheck/text()", null ); - if( healthcheck != null && !new File(healthcheck).exists() ) { - throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, "Service disabled"); + healthcheck = core.getSolrConfig().get("admin/healthcheck/text()", null ); + + String actionParam = params.get("action"); + ACTIONS action = null; + if (actionParam == null){ + action = ACTIONS.PING; } + else { + try { + action = ACTIONS.valueOf(actionParam.toUpperCase()); + } + catch (IllegalArgumentException iae){ + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, + "Unknown action: " + actionParam); + } + } + switch(action){ + case PING: + if( healthcheck != null && !new File(healthcheck).exists() ) { + throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, "Service disabled"); + } + handlePing(req, rsp); + break; + case ENABLE: + handleEnable(healthcheck,true); + break; + case DISABLE: + handleEnable(healthcheck,false); + break; + case STATUS: + if( healthcheck == null){ + SolrException e = new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, "healthcheck not configured"); + rsp.setException(e); + } + else { + if ( new File(healthcheck).exists() ){ + rsp.add( "status", "enabled"); + } + else { + rsp.add( "status", "disabled"); + } + } + } + + } + + protected void handlePing(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception + { + + SolrParams params = req.getParams(); + SolrCore core = req.getCore(); // Get the RequestHandler String qt = params.get( CommonParams.QT );//optional; you get the default otherwise @@ -79,7 +135,27 @@ public class PingRequestHandler extends RequestHandlerBase rsp.add( "status", "OK" ); } - + protected void handleEnable(String healthcheck, boolean enable) throws Exception + { + if (healthcheck == null) { + throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, + "No healthcheck file defined."); + } + File enableFile = new File(healthcheck); + if ( enable ) { + enableFile.createNewFile(); + + // write out when the file was created + FileWriter fw = new FileWriter(enableFile); + fw.write(formatRFC3339.format(new Date())); + fw.close(); + + } else { + if (enableFile.exists() && !enableFile.delete()){ + throw new SolrException( SolrException.ErrorCode.NOT_FOUND,"Did not successfully delete healthcheck file:'"+healthcheck+"'"); + } + } + } //////////////////////// SolrInfoMBeans methods ////////////////////// @Override diff --git a/solr/webapp/web/css/styles/dashboard.css b/solr/webapp/web/css/styles/dashboard.css index 2e48ec36435..32a926063df 100644 --- a/solr/webapp/web/css/styles/dashboard.css +++ b/solr/webapp/web/css/styles/dashboard.css @@ -4,19 +4,19 @@ width: 49%; } -#content #dashboard #statistics +#content #dashboard .fieldlist { float: left; } -#content #dashboard #statistics dt, -#content #dashboard #statistics dd +#content #dashboard .fieldlist dt, +#content #dashboard .fieldlist dd { display: block; float: left; } -#content #dashboard #statistics dt +#content #dashboard .fieldlist dt { clear: left; margin-right: 2%; @@ -24,28 +24,28 @@ width: 23%; } -#content #dashboard #statistics dd +#content #dashboard .fieldlist dd { width: 74%; } -#content #dashboard #statistics .index_optimized +#content #dashboard .fieldlist .index_optimized { margin-top: 10px; } -#content #dashboard #statistics .ico +#content #dashboard .fieldlist .ico { background-image: url( ../../img/ico/slash.png ); height: 20px; } -#content #dashboard #statistics .ico.ico-1 +#content #dashboard .fieldlist .ico.ico-1 { background-image: url( ../../img/ico/tick.png ); } -#content #dashboard #statistics .ico span +#content #dashboard .fieldlist .ico span { display: none; } @@ -111,4 +111,17 @@ #content #dashboard #replication.is-master h2 { background-image: url( ../../img/ico/node-master.png ); } #content #dashboard #replication.is-slave h2 { background-image: url( ../../img/ico/node-slave.png ); } #content #dashboard #dataimport h2 { background-image: url( ../../img/ico/document-import.png ); } -#content #dashboard #admin-extra h2 { background-image: url( ../../img/ico/plus-button.png ); } \ No newline at end of file +#content #dashboard #admin-extra h2 { background-image: url( ../../img/ico/plus-button.png ); } + +#content #dashboard #healthcheck .ico +{ + background-image: url( ../../img/ico/slash.png ); + height: 20px; + padding-left: 20px; + width: 60%; +} + +#content #dashboard #healthcheck .ico.ico-1 +{ + background-image: url( ../../img/ico/tick.png ); +} diff --git a/solr/webapp/web/js/scripts/dashboard.js b/solr/webapp/web/js/scripts/dashboard.js index 454139c7e5b..460fbba5181 100644 --- a/solr/webapp/web/js/scripts/dashboard.js +++ b/solr/webapp/web/js/scripts/dashboard.js @@ -15,6 +15,27 @@ limitations under the License. */ +var set_healthcheck_status = function( status ) +{ + var hc_button = $( '.healthcheck-status' ) + if ( status == 'enable' ) + { + hc_button.parents( 'dd' ) + .removeClass( 'ico-0' ) + .addClass( 'ico-1' ); + hc_button + .addClass( 'enabled' ) + .html( 'disable ping' ); + } else { + hc_button.parents( 'dd' ) + .removeClass( 'ico-1') + .addClass( 'ico-0' ); + hc_button + .removeClass( 'enabled' ) + .html( 'enable ping' ); + } +}; + // #/:core sammy.get ( @@ -410,8 +431,110 @@ sammy.get } } ); + + $.ajax + ( + { + url : core_basepath + '/admin/ping?action=status&wt=json', + dataType : 'json', + context : $( '#healthcheck', dashboard_element ), + beforeSend : function( xhr, settings ) + { + $( 'h2', this ) + .addClass( 'loader' ); + + $( '.message', this ) + .show() + .html( 'Loading' ); + + $( '.content', this ) + .hide(); + }, + success : function( response, text_status, xhr ) + { + $( '.message', this ) + .empty() + .hide(); + + $( '.content', this ) + .show(); + + var status_element = $( '.value.status', this ); + var toggle_button = $( '.healthcheck-status', this ); + var status = response['status']; + $( 'span', status_element ).html( status ); + + var action = ( response['status'] == 'enabled' ) ? 'enable' : 'disable'; + set_healthcheck_status(action); + + if( response['status'] == 'enabled' ) + { + status_element + .addClass( 'ico-1' ); + toggle_button + .addClass( 'enabled' ); + } + else + { + status_element + .addClass( 'ico-0' ); + } + + $( '.healthcheck-status', status_element ) + .die( 'click' ) + .live + ( + 'click', + function( event ) + { + var action = $(this).hasClass( 'enabled' ) ? 'disable' : 'enable'; + $.ajax + ( + { + url : core_basepath + '/admin/ping?action=' + action + '&wt=json', + dataType : 'json', + context : $( this ), + beforeSend : function( xhr, settings ) + { + this + .addClass( 'loader' ); + }, + success : function( response, text_status, xhr ) + { + set_healthcheck_status(action); + }, + error : function( xhr, text_status, error_thrown) + { + console.warn( 'd0h, enable broken!' ); + }, + complete : function( xhr, text_status ) + { + this + .removeClass( 'loader' ); + } + } + ); + } + ); + }, + error : function( xhr, text_status, error_thrown) + { + this + .addClass( 'disabled' ); + + $( '.message', this ) + .show() + .html( 'Ping request handler is not configured.' ); + }, + complete : function( xhr, text_status ) + { + $( 'h2', this ) + .removeClass( 'loader' ); + } + } + ); } ); } -); \ No newline at end of file +); diff --git a/solr/webapp/web/tpl/dashboard.html b/solr/webapp/web/tpl/dashboard.html index 4d0d8e24a43..66727c1132a 100644 --- a/solr/webapp/web/tpl/dashboard.html +++ b/solr/webapp/web/tpl/dashboard.html @@ -18,7 +18,7 @@ limitations under the License.
-
+

Statistics

@@ -137,5 +137,28 @@ limitations under the License.
+ +
+ +

Healthcheck

+ +
+
+
+ +
+
+ +
Status:
+
+ +
+
+
+ +
+ +
+ \ No newline at end of file