1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package org.apache.zookeeper.server.controller; 20 21 /** 22 * Set of commands that this controller can execute. Commands are comprised 23 * of an action and an optional parameter specific to that action. 24 */ 25 public class ControlCommand { 26 /** 27 * Actions available to the controller 28 */ 29 public enum Action { 30 // Simple "are you there" ping to confirm the controller is up and running. 31 PING, 32 // Shutdown everything, including CommandListener, ControllerService, Controller and the ZooKeeperServer. 33 SHUTDOWN, 34 // Close a connection triggering a client disconnect (and then reconnect attempt). 35 // No parameter indicates close all connections. Optional parameter indicates a specific session id (as long). 36 CLOSECONNECTION, 37 // More actions go here in the future (force drop sessions, etc). 38 EXPIRESESSION, 39 // Reject all future connections. No parameter required. 40 REJECTCONNECTIONS, 41 // Add latency to server replies. 42 // Optional parameter indicates time in milliseconds to delay 43 // (default = 1 second). 44 ADDDELAY, 45 // Fail requests. 46 // Optional parameter indicates how many requests to fail. 47 // (default = all requests until RESET). 48 FAILREQUESTS, 49 // Process requests but do not send a response. 50 // Optional parameter indicates how many requests to fail. 51 // (default = all requests until RESET). 52 NORESPONSE, 53 // No parameter indicates fail all requests. 54 // Optional parameter indicates undo all the chaotic action commands 55 // (reject connections, add delay, fail requests, eat requests and so on...). 56 RESET, 57 // Force the quorum to elect a new leader. 58 ELECTNEWLEADER, 59 // More actions go here in the future... 60 } 61 62 public static final String ENDPOINT = "command"; 63 public static final String ENDPOINT_PREFIX = ENDPOINT + "/"; 64 65 private Action action; getAction()66 public Action getAction() { 67 return action; 68 } 69 70 private String parameter; getParameter()71 protected String getParameter() { 72 return parameter; 73 } 74 ControlCommand(Action action)75 public ControlCommand(Action action) { 76 this(action, null); 77 } 78 ControlCommand(Action action, String param)79 public ControlCommand(Action action, String param) { 80 this.action = action; 81 this.parameter = param; 82 } 83 84 /** 85 * Create a REST command uri. 86 * @param action The 'verb' of the command. 87 * @param parameter The optional parameter. 88 * @return A string to send to the server as the end of the Uri. 89 */ createCommandUri(Action action, String parameter)90 public static String createCommandUri(Action action, String parameter) { 91 return ENDPOINT_PREFIX + action.toString() + (parameter != null && !parameter.isEmpty() ? "/" + parameter : ""); 92 } 93 94 /** 95 * Parse a Uri into the required Command action and parameter. 96 * @param commandUri the properly formatted Uri. 97 */ parseUri(String commandUri)98 public static ControlCommand parseUri(String commandUri) { 99 if (commandUri == null) { 100 throw new IllegalArgumentException("commandUri can't be null."); 101 } 102 103 if (!commandUri.startsWith(ENDPOINT_PREFIX)) { 104 throw new IllegalArgumentException("Missing required prefix: " + ENDPOINT_PREFIX); 105 } 106 107 String uri = commandUri.substring(ENDPOINT_PREFIX.length()); 108 String name; 109 String param; 110 111 int separatorIndex = uri.indexOf('/'); 112 if (separatorIndex < 0) { 113 name = uri; 114 param = null; 115 } else { 116 name = uri.substring(0, separatorIndex); 117 param = uri.substring(separatorIndex + 1); 118 } 119 120 return new ControlCommand(Action.valueOf(name.toUpperCase()), param); 121 } 122 } 123