summaryrefslogtreecommitdiff
path: root/core/src/main/java/org/elasticsearch/action/admin/cluster/allocation/ClusterAllocationExplainRequest.java
blob: d80e58232a50fd257afc45f671f9f8da9192e735 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch 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.elasticsearch.action.admin.cluster.allocation;

import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.master.MasterNodeRequest;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.XContentParser;

import java.io.IOException;

import static org.elasticsearch.action.ValidateActions.addValidationError;

/**
 * A request to explain the allocation of a shard in the cluster
 */
public class ClusterAllocationExplainRequest extends MasterNodeRequest<ClusterAllocationExplainRequest> {

    private static ObjectParser<ClusterAllocationExplainRequest, Void> PARSER = new ObjectParser<>("cluster/allocation/explain");
    static {
        PARSER.declareString(ClusterAllocationExplainRequest::setIndex, new ParseField("index"));
        PARSER.declareInt(ClusterAllocationExplainRequest::setShard, new ParseField("shard"));
        PARSER.declareBoolean(ClusterAllocationExplainRequest::setPrimary, new ParseField("primary"));
        PARSER.declareString(ClusterAllocationExplainRequest::setCurrentNode, new ParseField("current_node"));
    }

    @Nullable
    private String index;
    @Nullable
    private Integer shard;
    @Nullable
    private Boolean primary;
    @Nullable
    private String currentNode;
    private boolean includeYesDecisions = false;
    private boolean includeDiskInfo = false;

    /**
     * Create a new allocation explain request to explain any unassigned shard in the cluster.
     */
    public ClusterAllocationExplainRequest() {
        this.index = null;
        this.shard = null;
        this.primary = null;
        this.currentNode = null;
    }

    /**
     * Create a new allocation explain request. If {@code primary} is false, the first unassigned replica
     * will be picked for explanation. If no replicas are unassigned, the first assigned replica will
     * be explained.
     *
     * Package private for testing.
     */
    ClusterAllocationExplainRequest(String index, int shard, boolean primary, @Nullable String currentNode) {
        this.index = index;
        this.shard = shard;
        this.primary = primary;
        this.currentNode = currentNode;
    }

    @Override
    public ActionRequestValidationException validate() {
        ActionRequestValidationException validationException = null;
        if (this.useAnyUnassignedShard() == false) {
            if (this.index == null) {
                validationException = addValidationError("index must be specified", validationException);
            }
            if (this.shard == null) {
                validationException = addValidationError("shard must be specified", validationException);
            }
            if (this.primary == null) {
                validationException = addValidationError("primary must be specified", validationException);
            }
        }
        return validationException;
    }

    /**
     * Returns {@code true} iff the first unassigned shard is to be used
     */
    public boolean useAnyUnassignedShard() {
        return this.index == null && this.shard == null && this.primary == null && this.currentNode == null;
    }

    /**
     * Sets the index name of the shard to explain.
     */
    public ClusterAllocationExplainRequest setIndex(String index) {
        this.index = index;
        return this;
    }

    /**
     * Returns the index name of the shard to explain, or {@code null} to use any unassigned shard (see {@link #useAnyUnassignedShard()}).
     */
    @Nullable
    public String getIndex() {
        return this.index;
    }

    /**
     * Sets the shard id of the shard to explain.
     */
    public ClusterAllocationExplainRequest setShard(Integer shard) {
        this.shard = shard;
        return this;
    }

    /**
     * Returns the shard id of the shard to explain, or {@code null} to use any unassigned shard (see {@link #useAnyUnassignedShard()}).
     */
    @Nullable
    public Integer getShard() {
        return this.shard;
    }

    /**
     * Sets whether to explain the allocation of the primary shard or a replica shard copy
     * for the shard id (see {@link #getShard()}).
     */
    public ClusterAllocationExplainRequest setPrimary(Boolean primary) {
        this.primary = primary;
        return this;
    }

    /**
     * Returns {@code true} if explaining the primary shard for the shard id (see {@link #getShard()}),
     * {@code false} if explaining a replica shard copy for the shard id, or {@code null} to use any
     * unassigned shard (see {@link #useAnyUnassignedShard()}).
     */
    @Nullable
    public Boolean isPrimary() {
        return this.primary;
    }

    /**
     * Requests the explain API to explain an already assigned replica shard currently allocated to
     * the given node.
     */
    public ClusterAllocationExplainRequest setCurrentNode(String currentNodeId) {
        this.currentNode = currentNodeId;
        return this;
    }

    /**
     * Returns the node holding the replica shard to be explained.  Returns {@code null} if any replica shard
     * can be explained.
     */
    @Nullable
    public String getCurrentNode() {
        return currentNode;
    }

    /**
     * Set to {@code true} to include yes decisions for a particular node.
     */
    public void includeYesDecisions(boolean includeYesDecisions) {
        this.includeYesDecisions = includeYesDecisions;
    }

    /**
     * Returns {@code true} if yes decisions should be included.  Otherwise only "no" and "throttle"
     * decisions are returned.
     */
    public boolean includeYesDecisions() {
        return this.includeYesDecisions;
    }

    /**
     * Set to {@code true} to include information about the gathered disk information of nodes in the cluster.
     */
    public void includeDiskInfo(boolean includeDiskInfo) {
        this.includeDiskInfo = includeDiskInfo;
    }

    /**
     * Returns {@code true} if information about disk usage and shard sizes should also be returned.
     */
    public boolean includeDiskInfo() {
        return this.includeDiskInfo;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("ClusterAllocationExplainRequest[");
        if (this.useAnyUnassignedShard()) {
            sb.append("useAnyUnassignedShard=true");
        } else {
            sb.append("index=").append(index);
            sb.append(",shard=").append(shard);
            sb.append(",primary?=").append(primary);
            if (currentNode != null) {
                sb.append(",currentNode=").append(currentNode);
            }
        }
        sb.append(",includeYesDecisions?=").append(includeYesDecisions);
        return sb.toString();
    }

    public static ClusterAllocationExplainRequest parse(XContentParser parser) throws IOException {
        return PARSER.parse(parser, new ClusterAllocationExplainRequest(), null);
    }

    @Override
    public void readFrom(StreamInput in) throws IOException {
        checkVersion(in.getVersion());
        super.readFrom(in);
        this.index = in.readOptionalString();
        this.shard = in.readOptionalVInt();
        this.primary = in.readOptionalBoolean();
        this.currentNode = in.readOptionalString();
        this.includeYesDecisions = in.readBoolean();
        this.includeDiskInfo = in.readBoolean();
    }

    @Override
    public void writeTo(StreamOutput out) throws IOException {
        checkVersion(out.getVersion());
        super.writeTo(out);
        out.writeOptionalString(index);
        out.writeOptionalVInt(shard);
        out.writeOptionalBoolean(primary);
        out.writeOptionalString(currentNode);
        out.writeBoolean(includeYesDecisions);
        out.writeBoolean(includeDiskInfo);
    }

    private void checkVersion(Version version) {
        if (version.before(Version.V_5_2_0_UNRELEASED)) {
            throw new IllegalArgumentException("cannot explain shards in a mixed-cluster with pre-" + Version.V_5_2_0_UNRELEASED +
                                               " nodes, node version [" + version + "]");
        }
    }
}