mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-23 13:26:02 +00:00
Add BootstrapContext to expose settings and recovered state to bootstrap checks (#26628)
This exposes the node settings and the persistent part of the cluster state to the bootstrap checks to allow plugins to enforce certain preconditions based on the recovered state.
This commit is contained in:
parent
2eaf7534f3
commit
b4de2a6f28
@ -212,9 +212,9 @@ final class Bootstrap {
|
|||||||
node = new Node(environment) {
|
node = new Node(environment) {
|
||||||
@Override
|
@Override
|
||||||
protected void validateNodeBeforeAcceptingRequests(
|
protected void validateNodeBeforeAcceptingRequests(
|
||||||
final Settings settings,
|
final BootstrapContext context,
|
||||||
final BoundTransportAddress boundTransportAddress, List<BootstrapCheck> checks) throws NodeValidationException {
|
final BoundTransportAddress boundTransportAddress, List<BootstrapCheck> checks) throws NodeValidationException {
|
||||||
BootstrapChecks.check(settings, boundTransportAddress, checks);
|
BootstrapChecks.check(context, boundTransportAddress, checks);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,10 @@ public interface BootstrapCheck {
|
|||||||
/**
|
/**
|
||||||
* Test if the node fails the check.
|
* Test if the node fails the check.
|
||||||
*
|
*
|
||||||
|
* @param context the bootstrap context for more sophisticated checks
|
||||||
* @return {@code true} if the node failed the check
|
* @return {@code true} if the node failed the check
|
||||||
*/
|
*/
|
||||||
boolean check();
|
boolean check(BootstrapContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The error message for a failed check.
|
* The error message for a failed check.
|
||||||
@ -41,5 +42,4 @@ public interface BootstrapCheck {
|
|||||||
default boolean alwaysEnforce() {
|
default boolean alwaysEnforce() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@ import org.apache.lucene.util.Constants;
|
|||||||
import org.elasticsearch.common.SuppressForbidden;
|
import org.elasticsearch.common.SuppressForbidden;
|
||||||
import org.elasticsearch.common.io.PathUtils;
|
import org.elasticsearch.common.io.PathUtils;
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
import org.elasticsearch.common.logging.Loggers;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
|
||||||
import org.elasticsearch.common.transport.BoundTransportAddress;
|
import org.elasticsearch.common.transport.BoundTransportAddress;
|
||||||
import org.elasticsearch.common.transport.TransportAddress;
|
import org.elasticsearch.common.transport.TransportAddress;
|
||||||
import org.elasticsearch.discovery.DiscoveryModule;
|
import org.elasticsearch.discovery.DiscoveryModule;
|
||||||
@ -65,18 +64,18 @@ final class BootstrapChecks {
|
|||||||
* {@code es.enforce.bootstrap.checks} is set to {@code true} then the bootstrap checks will be enforced regardless of whether or not
|
* {@code es.enforce.bootstrap.checks} is set to {@code true} then the bootstrap checks will be enforced regardless of whether or not
|
||||||
* the transport protocol is bound to a non-loopback interface.
|
* the transport protocol is bound to a non-loopback interface.
|
||||||
*
|
*
|
||||||
* @param settings the current node settings
|
* @param context the current node bootstrap context
|
||||||
* @param boundTransportAddress the node network bindings
|
* @param boundTransportAddress the node network bindings
|
||||||
*/
|
*/
|
||||||
static void check(final Settings settings, final BoundTransportAddress boundTransportAddress, List<BootstrapCheck> additionalChecks)
|
static void check(final BootstrapContext context, final BoundTransportAddress boundTransportAddress,
|
||||||
throws NodeValidationException {
|
List<BootstrapCheck> additionalChecks) throws NodeValidationException {
|
||||||
final List<BootstrapCheck> builtInChecks = checks(settings);
|
final List<BootstrapCheck> builtInChecks = checks();
|
||||||
final List<BootstrapCheck> combinedChecks = new ArrayList<>(builtInChecks);
|
final List<BootstrapCheck> combinedChecks = new ArrayList<>(builtInChecks);
|
||||||
combinedChecks.addAll(additionalChecks);
|
combinedChecks.addAll(additionalChecks);
|
||||||
check(
|
check( context,
|
||||||
enforceLimits(boundTransportAddress, DiscoveryModule.DISCOVERY_TYPE_SETTING.get(settings)),
|
enforceLimits(boundTransportAddress, DiscoveryModule.DISCOVERY_TYPE_SETTING.get(context.settings)),
|
||||||
Collections.unmodifiableList(combinedChecks),
|
Collections.unmodifiableList(combinedChecks),
|
||||||
Node.NODE_NAME_SETTING.get(settings));
|
Node.NODE_NAME_SETTING.get(context.settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,15 +83,17 @@ final class BootstrapChecks {
|
|||||||
* property {@code es.enforce.bootstrap.checks} is set to {@code true} then the bootstrap checks will be enforced regardless of whether
|
* property {@code es.enforce.bootstrap.checks} is set to {@code true} then the bootstrap checks will be enforced regardless of whether
|
||||||
* or not the transport protocol is bound to a non-loopback interface.
|
* or not the transport protocol is bound to a non-loopback interface.
|
||||||
*
|
*
|
||||||
|
* @param context the current node boostrap context
|
||||||
* @param enforceLimits {@code true} if the checks should be enforced or otherwise warned
|
* @param enforceLimits {@code true} if the checks should be enforced or otherwise warned
|
||||||
* @param checks the checks to execute
|
* @param checks the checks to execute
|
||||||
* @param nodeName the node name to be used as a logging prefix
|
* @param nodeName the node name to be used as a logging prefix
|
||||||
*/
|
*/
|
||||||
static void check(
|
static void check(
|
||||||
|
final BootstrapContext context,
|
||||||
final boolean enforceLimits,
|
final boolean enforceLimits,
|
||||||
final List<BootstrapCheck> checks,
|
final List<BootstrapCheck> checks,
|
||||||
final String nodeName) throws NodeValidationException {
|
final String nodeName) throws NodeValidationException {
|
||||||
check(enforceLimits, checks, Loggers.getLogger(BootstrapChecks.class, nodeName));
|
check(context, enforceLimits, checks, Loggers.getLogger(BootstrapChecks.class, nodeName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,11 +101,13 @@ final class BootstrapChecks {
|
|||||||
* property {@code es.enforce.bootstrap.checks }is set to {@code true} then the bootstrap checks will be enforced regardless of whether
|
* property {@code es.enforce.bootstrap.checks }is set to {@code true} then the bootstrap checks will be enforced regardless of whether
|
||||||
* or not the transport protocol is bound to a non-loopback interface.
|
* or not the transport protocol is bound to a non-loopback interface.
|
||||||
*
|
*
|
||||||
|
* @param context the current node boostrap context
|
||||||
* @param enforceLimits {@code true} if the checks should be enforced or otherwise warned
|
* @param enforceLimits {@code true} if the checks should be enforced or otherwise warned
|
||||||
* @param checks the checks to execute
|
* @param checks the checks to execute
|
||||||
* @param logger the logger to
|
* @param logger the logger to
|
||||||
*/
|
*/
|
||||||
static void check(
|
static void check(
|
||||||
|
final BootstrapContext context,
|
||||||
final boolean enforceLimits,
|
final boolean enforceLimits,
|
||||||
final List<BootstrapCheck> checks,
|
final List<BootstrapCheck> checks,
|
||||||
final Logger logger) throws NodeValidationException {
|
final Logger logger) throws NodeValidationException {
|
||||||
@ -134,7 +137,7 @@ final class BootstrapChecks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final BootstrapCheck check : checks) {
|
for (final BootstrapCheck check : checks) {
|
||||||
if (check.check()) {
|
if (check.check(context)) {
|
||||||
if (!(enforceLimits || enforceBootstrapChecks) && !check.alwaysEnforce()) {
|
if (!(enforceLimits || enforceBootstrapChecks) && !check.alwaysEnforce()) {
|
||||||
ignoredErrors.add(check.errorMessage());
|
ignoredErrors.add(check.errorMessage());
|
||||||
} else {
|
} else {
|
||||||
@ -180,13 +183,13 @@ final class BootstrapChecks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the list of checks to execute
|
// the list of checks to execute
|
||||||
static List<BootstrapCheck> checks(final Settings settings) {
|
static List<BootstrapCheck> checks() {
|
||||||
final List<BootstrapCheck> checks = new ArrayList<>();
|
final List<BootstrapCheck> checks = new ArrayList<>();
|
||||||
checks.add(new HeapSizeCheck());
|
checks.add(new HeapSizeCheck());
|
||||||
final FileDescriptorCheck fileDescriptorCheck
|
final FileDescriptorCheck fileDescriptorCheck
|
||||||
= Constants.MAC_OS_X ? new OsXFileDescriptorCheck() : new FileDescriptorCheck();
|
= Constants.MAC_OS_X ? new OsXFileDescriptorCheck() : new FileDescriptorCheck();
|
||||||
checks.add(fileDescriptorCheck);
|
checks.add(fileDescriptorCheck);
|
||||||
checks.add(new MlockallCheck(BootstrapSettings.MEMORY_LOCK_SETTING.get(settings)));
|
checks.add(new MlockallCheck());
|
||||||
if (Constants.LINUX) {
|
if (Constants.LINUX) {
|
||||||
checks.add(new MaxNumberOfThreadsCheck());
|
checks.add(new MaxNumberOfThreadsCheck());
|
||||||
}
|
}
|
||||||
@ -201,7 +204,7 @@ final class BootstrapChecks {
|
|||||||
}
|
}
|
||||||
checks.add(new ClientJvmCheck());
|
checks.add(new ClientJvmCheck());
|
||||||
checks.add(new UseSerialGCCheck());
|
checks.add(new UseSerialGCCheck());
|
||||||
checks.add(new SystemCallFilterCheck(BootstrapSettings.SYSTEM_CALL_FILTER_SETTING.get(settings)));
|
checks.add(new SystemCallFilterCheck());
|
||||||
checks.add(new OnErrorCheck());
|
checks.add(new OnErrorCheck());
|
||||||
checks.add(new OnOutOfMemoryErrorCheck());
|
checks.add(new OnOutOfMemoryErrorCheck());
|
||||||
checks.add(new EarlyAccessCheck());
|
checks.add(new EarlyAccessCheck());
|
||||||
@ -212,7 +215,7 @@ final class BootstrapChecks {
|
|||||||
static class HeapSizeCheck implements BootstrapCheck {
|
static class HeapSizeCheck implements BootstrapCheck {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
final long initialHeapSize = getInitialHeapSize();
|
final long initialHeapSize = getInitialHeapSize();
|
||||||
final long maxHeapSize = getMaxHeapSize();
|
final long maxHeapSize = getMaxHeapSize();
|
||||||
return initialHeapSize != 0 && maxHeapSize != 0 && initialHeapSize != maxHeapSize;
|
return initialHeapSize != 0 && maxHeapSize != 0 && initialHeapSize != maxHeapSize;
|
||||||
@ -268,7 +271,7 @@ final class BootstrapChecks {
|
|||||||
this.limit = limit;
|
this.limit = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean check() {
|
public final boolean check(BootstrapContext context) {
|
||||||
final long maxFileDescriptorCount = getMaxFileDescriptorCount();
|
final long maxFileDescriptorCount = getMaxFileDescriptorCount();
|
||||||
return maxFileDescriptorCount != -1 && maxFileDescriptorCount < limit;
|
return maxFileDescriptorCount != -1 && maxFileDescriptorCount < limit;
|
||||||
}
|
}
|
||||||
@ -292,15 +295,9 @@ final class BootstrapChecks {
|
|||||||
|
|
||||||
static class MlockallCheck implements BootstrapCheck {
|
static class MlockallCheck implements BootstrapCheck {
|
||||||
|
|
||||||
private final boolean mlockallSet;
|
|
||||||
|
|
||||||
MlockallCheck(final boolean mlockAllSet) {
|
|
||||||
this.mlockallSet = mlockAllSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return mlockallSet && !isMemoryLocked();
|
return BootstrapSettings.MEMORY_LOCK_SETTING.get(context.settings) && !isMemoryLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -321,7 +318,7 @@ final class BootstrapChecks {
|
|||||||
private static final long MAX_NUMBER_OF_THREADS_THRESHOLD = 1 << 12;
|
private static final long MAX_NUMBER_OF_THREADS_THRESHOLD = 1 << 12;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return getMaxNumberOfThreads() != -1 && getMaxNumberOfThreads() < MAX_NUMBER_OF_THREADS_THRESHOLD;
|
return getMaxNumberOfThreads() != -1 && getMaxNumberOfThreads() < MAX_NUMBER_OF_THREADS_THRESHOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,7 +342,7 @@ final class BootstrapChecks {
|
|||||||
static class MaxSizeVirtualMemoryCheck implements BootstrapCheck {
|
static class MaxSizeVirtualMemoryCheck implements BootstrapCheck {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return getMaxSizeVirtualMemory() != Long.MIN_VALUE && getMaxSizeVirtualMemory() != getRlimInfinity();
|
return getMaxSizeVirtualMemory() != Long.MIN_VALUE && getMaxSizeVirtualMemory() != getRlimInfinity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +373,7 @@ final class BootstrapChecks {
|
|||||||
static class MaxFileSizeCheck implements BootstrapCheck {
|
static class MaxFileSizeCheck implements BootstrapCheck {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
final long maxFileSize = getMaxFileSize();
|
final long maxFileSize = getMaxFileSize();
|
||||||
return maxFileSize != Long.MIN_VALUE && maxFileSize != getRlimInfinity();
|
return maxFileSize != Long.MIN_VALUE && maxFileSize != getRlimInfinity();
|
||||||
}
|
}
|
||||||
@ -405,7 +402,7 @@ final class BootstrapChecks {
|
|||||||
private static final long LIMIT = 1 << 18;
|
private static final long LIMIT = 1 << 18;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return getMaxMapCount() != -1 && getMaxMapCount() < LIMIT;
|
return getMaxMapCount() != -1 && getMaxMapCount() < LIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,7 +467,7 @@ final class BootstrapChecks {
|
|||||||
static class ClientJvmCheck implements BootstrapCheck {
|
static class ClientJvmCheck implements BootstrapCheck {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return getVmName().toLowerCase(Locale.ROOT).contains("client");
|
return getVmName().toLowerCase(Locale.ROOT).contains("client");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +493,7 @@ final class BootstrapChecks {
|
|||||||
static class UseSerialGCCheck implements BootstrapCheck {
|
static class UseSerialGCCheck implements BootstrapCheck {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return getUseSerialGC().equals("true");
|
return getUseSerialGC().equals("true");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,15 +518,9 @@ final class BootstrapChecks {
|
|||||||
*/
|
*/
|
||||||
static class SystemCallFilterCheck implements BootstrapCheck {
|
static class SystemCallFilterCheck implements BootstrapCheck {
|
||||||
|
|
||||||
private final boolean areSystemCallFiltersEnabled;
|
|
||||||
|
|
||||||
SystemCallFilterCheck(final boolean areSystemCallFiltersEnabled) {
|
|
||||||
this.areSystemCallFiltersEnabled = areSystemCallFiltersEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return areSystemCallFiltersEnabled && !isSystemCallFilterInstalled();
|
return BootstrapSettings.SYSTEM_CALL_FILTER_SETTING.get(context.settings) && !isSystemCallFilterInstalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// visible for testing
|
// visible for testing
|
||||||
@ -548,7 +539,7 @@ final class BootstrapChecks {
|
|||||||
abstract static class MightForkCheck implements BootstrapCheck {
|
abstract static class MightForkCheck implements BootstrapCheck {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return isSystemCallFilterInstalled() && mightFork();
|
return isSystemCallFilterInstalled() && mightFork();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +614,7 @@ final class BootstrapChecks {
|
|||||||
static class EarlyAccessCheck implements BootstrapCheck {
|
static class EarlyAccessCheck implements BootstrapCheck {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return "Oracle Corporation".equals(jvmVendor()) && javaVersion().endsWith("-ea");
|
return "Oracle Corporation".equals(jvmVendor()) && javaVersion().endsWith("-ea");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,7 +642,7 @@ final class BootstrapChecks {
|
|||||||
static class G1GCCheck implements BootstrapCheck {
|
static class G1GCCheck implements BootstrapCheck {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
if ("Oracle Corporation".equals(jvmVendor()) && isJava8() && isG1GCEnabled()) {
|
if ("Oracle Corporation".equals(jvmVendor()) && isJava8() && isG1GCEnabled()) {
|
||||||
final String jvmVersion = jvmVersion();
|
final String jvmVersion = jvmVersion();
|
||||||
// HotSpot versions on Java 8 match this regular expression; note that this changes with Java 9 after JEP-223
|
// HotSpot versions on Java 8 match this regular expression; note that this changes with Java 9 after JEP-223
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.bootstrap;
|
||||||
|
|
||||||
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context that is passed to every bootstrap check to make decisions on.
|
||||||
|
*/
|
||||||
|
public class BootstrapContext {
|
||||||
|
/**
|
||||||
|
* The nodes settings
|
||||||
|
*/
|
||||||
|
public final Settings settings;
|
||||||
|
/**
|
||||||
|
* The nodes local state metadata loaded on startup
|
||||||
|
*/
|
||||||
|
public final MetaData metaData;
|
||||||
|
|
||||||
|
public BootstrapContext(Settings settings, MetaData metaData) {
|
||||||
|
this.settings = settings;
|
||||||
|
this.metaData = metaData;
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,7 @@ import org.elasticsearch.env.NodeEnvironment;
|
|||||||
import org.elasticsearch.index.Index;
|
import org.elasticsearch.index.Index;
|
||||||
import org.elasticsearch.plugins.MetaDataUpgrader;
|
import org.elasticsearch.plugins.MetaDataUpgrader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.DirectoryStream;
|
import java.nio.file.DirectoryStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -114,7 +115,7 @@ public class GatewayMetaState extends AbstractComponent implements ClusterStateA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetaData loadMetaState() throws Exception {
|
public MetaData loadMetaState() throws IOException {
|
||||||
return metaStateService.loadFullState();
|
return metaStateService.loadFullState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ public class MetaStateService extends AbstractComponent {
|
|||||||
* Loads the full state, which includes both the global state and all the indices
|
* Loads the full state, which includes both the global state and all the indices
|
||||||
* meta state.
|
* meta state.
|
||||||
*/
|
*/
|
||||||
MetaData loadFullState() throws Exception {
|
MetaData loadFullState() throws IOException {
|
||||||
MetaData globalMetaData = loadGlobalState();
|
MetaData globalMetaData = loadGlobalState();
|
||||||
MetaData.Builder metaDataBuilder;
|
MetaData.Builder metaDataBuilder;
|
||||||
if (globalMetaData != null) {
|
if (globalMetaData != null) {
|
||||||
|
@ -35,6 +35,7 @@ import org.elasticsearch.action.search.SearchTransportService;
|
|||||||
import org.elasticsearch.action.support.TransportAction;
|
import org.elasticsearch.action.support.TransportAction;
|
||||||
import org.elasticsearch.action.update.UpdateHelper;
|
import org.elasticsearch.action.update.UpdateHelper;
|
||||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||||
|
import org.elasticsearch.bootstrap.BootstrapContext;
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
import org.elasticsearch.client.node.NodeClient;
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
import org.elasticsearch.cluster.ClusterInfo;
|
import org.elasticsearch.cluster.ClusterInfo;
|
||||||
@ -86,6 +87,7 @@ import org.elasticsearch.discovery.DiscoverySettings;
|
|||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.env.NodeEnvironment;
|
import org.elasticsearch.env.NodeEnvironment;
|
||||||
import org.elasticsearch.gateway.GatewayAllocator;
|
import org.elasticsearch.gateway.GatewayAllocator;
|
||||||
|
import org.elasticsearch.gateway.GatewayMetaState;
|
||||||
import org.elasticsearch.gateway.GatewayModule;
|
import org.elasticsearch.gateway.GatewayModule;
|
||||||
import org.elasticsearch.gateway.GatewayService;
|
import org.elasticsearch.gateway.GatewayService;
|
||||||
import org.elasticsearch.gateway.MetaStateService;
|
import org.elasticsearch.gateway.MetaStateService;
|
||||||
@ -139,6 +141,7 @@ import org.elasticsearch.watcher.ResourceWatcherService;
|
|||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
@ -604,7 +607,23 @@ public class Node implements Closeable {
|
|||||||
assert localNodeFactory.getNode() != null;
|
assert localNodeFactory.getNode() != null;
|
||||||
assert transportService.getLocalNode().equals(localNodeFactory.getNode())
|
assert transportService.getLocalNode().equals(localNodeFactory.getNode())
|
||||||
: "transportService has a different local node than the factory provided";
|
: "transportService has a different local node than the factory provided";
|
||||||
validateNodeBeforeAcceptingRequests(settings, transportService.boundAddress(), pluginsService.filterPlugins(Plugin.class).stream()
|
final MetaData onDiskMetadata;
|
||||||
|
try {
|
||||||
|
// we load the global state here (the persistent part of the cluster state stored on disk) to
|
||||||
|
// pass it to the bootstrap checks to allow plugins to enforce certain preconditions based on the recovered state.
|
||||||
|
if (DiscoveryNode.isMasterNode(settings) || DiscoveryNode.isDataNode(settings)) {
|
||||||
|
onDiskMetadata = injector.getInstance(GatewayMetaState.class).loadMetaState();
|
||||||
|
} else {
|
||||||
|
onDiskMetadata = MetaData.EMPTY_META_DATA;
|
||||||
|
}
|
||||||
|
assert onDiskMetadata != null : "metadata is null but shouldn't"; // this is never null
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
validateNodeBeforeAcceptingRequests(new BootstrapContext(settings, onDiskMetadata), transportService.boundAddress(), pluginsService
|
||||||
|
.filterPlugins(Plugin
|
||||||
|
.class)
|
||||||
|
.stream()
|
||||||
.flatMap(p -> p.getBootstrapChecks().stream()).collect(Collectors.toList()));
|
.flatMap(p -> p.getBootstrapChecks().stream()).collect(Collectors.toList()));
|
||||||
|
|
||||||
clusterService.addStateApplier(transportService.getTaskManager());
|
clusterService.addStateApplier(transportService.getTaskManager());
|
||||||
@ -811,13 +830,13 @@ public class Node implements Closeable {
|
|||||||
* and before the network service starts accepting incoming network
|
* and before the network service starts accepting incoming network
|
||||||
* requests.
|
* requests.
|
||||||
*
|
*
|
||||||
* @param settings the fully-resolved settings
|
* @param context the bootstrap context for this node
|
||||||
* @param boundTransportAddress the network addresses the node is
|
* @param boundTransportAddress the network addresses the node is
|
||||||
* bound and publishing to
|
* bound and publishing to
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
protected void validateNodeBeforeAcceptingRequests(
|
protected void validateNodeBeforeAcceptingRequests(
|
||||||
final Settings settings,
|
final BootstrapContext context,
|
||||||
final BoundTransportAddress boundTransportAddress, List<BootstrapCheck> bootstrapChecks) throws NodeValidationException {
|
final BoundTransportAddress boundTransportAddress, List<BootstrapCheck> bootstrapChecks) throws NodeValidationException {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* An exception thrown during node validation. Node validation runs immediately before a node
|
* An exception thrown during node validation. Node validation runs immediately before a node
|
||||||
* begins accepting network requests in
|
* begins accepting network requests in
|
||||||
* {@link Node#validateNodeBeforeAcceptingRequests(Settings, BoundTransportAddress, List)}. This exception is a checked exception that
|
* {@link Node#validateNodeBeforeAcceptingRequests(org.elasticsearch.bootstrap.BootstrapContext, BoundTransportAddress, List)}.
|
||||||
* is declared as thrown from this method for the purpose of bubbling up to the user.
|
* This exception is a checked exception that is declared as thrown from this method for the purpose of bubbling up to the user.
|
||||||
*/
|
*/
|
||||||
public class NodeValidationException extends Exception {
|
public class NodeValidationException extends Exception {
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.bootstrap;
|
|||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.lucene.util.Constants;
|
import org.apache.lucene.util.Constants;
|
||||||
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.transport.BoundTransportAddress;
|
import org.elasticsearch.common.transport.BoundTransportAddress;
|
||||||
import org.elasticsearch.common.transport.TransportAddress;
|
import org.elasticsearch.common.transport.TransportAddress;
|
||||||
@ -51,6 +52,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
public class BootstrapChecksTests extends ESTestCase {
|
public class BootstrapChecksTests extends ESTestCase {
|
||||||
|
private static final BootstrapContext defaultContext = new BootstrapContext(Settings.EMPTY, MetaData.EMPTY_META_DATA);
|
||||||
|
|
||||||
public void testNonProductionMode() throws NodeValidationException {
|
public void testNonProductionMode() throws NodeValidationException {
|
||||||
// nothing should happen since we are in non-production mode
|
// nothing should happen since we are in non-production mode
|
||||||
@ -64,18 +66,18 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
BoundTransportAddress boundTransportAddress = mock(BoundTransportAddress.class);
|
BoundTransportAddress boundTransportAddress = mock(BoundTransportAddress.class);
|
||||||
when(boundTransportAddress.boundAddresses()).thenReturn(transportAddresses.toArray(new TransportAddress[0]));
|
when(boundTransportAddress.boundAddresses()).thenReturn(transportAddresses.toArray(new TransportAddress[0]));
|
||||||
when(boundTransportAddress.publishAddress()).thenReturn(publishAddress);
|
when(boundTransportAddress.publishAddress()).thenReturn(publishAddress);
|
||||||
BootstrapChecks.check(Settings.EMPTY, boundTransportAddress, Collections.emptyList());
|
BootstrapChecks.check(defaultContext, boundTransportAddress, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNoLogMessageInNonProductionMode() throws NodeValidationException {
|
public void testNoLogMessageInNonProductionMode() throws NodeValidationException {
|
||||||
final Logger logger = mock(Logger.class);
|
final Logger logger = mock(Logger.class);
|
||||||
BootstrapChecks.check(false, Collections.emptyList(), logger);
|
BootstrapChecks.check(defaultContext, false, Collections.emptyList(), logger);
|
||||||
verifyNoMoreInteractions(logger);
|
verifyNoMoreInteractions(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLogMessageInProductionMode() throws NodeValidationException {
|
public void testLogMessageInProductionMode() throws NodeValidationException {
|
||||||
final Logger logger = mock(Logger.class);
|
final Logger logger = mock(Logger.class);
|
||||||
BootstrapChecks.check(true, Collections.emptyList(), logger);
|
BootstrapChecks.check(defaultContext, true, Collections.emptyList(), logger);
|
||||||
verify(logger).info("bound or publishing to a non-loopback or non-link-local address, enforcing bootstrap checks");
|
verify(logger).info("bound or publishing to a non-loopback or non-link-local address, enforcing bootstrap checks");
|
||||||
verifyNoMoreInteractions(logger);
|
verifyNoMoreInteractions(logger);
|
||||||
}
|
}
|
||||||
@ -126,7 +128,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
final List<BootstrapCheck> checks = Arrays.asList(
|
final List<BootstrapCheck> checks = Arrays.asList(
|
||||||
new BootstrapCheck() {
|
new BootstrapCheck() {
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +139,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
},
|
},
|
||||||
new BootstrapCheck() {
|
new BootstrapCheck() {
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +151,8 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final NodeValidationException e =
|
final NodeValidationException e =
|
||||||
expectThrows(NodeValidationException.class, () -> BootstrapChecks.check(true, checks, "testExceptionAggregation"));
|
expectThrows(NodeValidationException.class,
|
||||||
|
() -> BootstrapChecks.check(defaultContext, true, checks, "testExceptionAggregation"));
|
||||||
assertThat(e, hasToString(allOf(containsString("bootstrap checks failed"), containsString("first"), containsString("second"))));
|
assertThat(e, hasToString(allOf(containsString("bootstrap checks failed"), containsString("first"), containsString("second"))));
|
||||||
final Throwable[] suppressed = e.getSuppressed();
|
final Throwable[] suppressed = e.getSuppressed();
|
||||||
assertThat(suppressed.length, equalTo(2));
|
assertThat(suppressed.length, equalTo(2));
|
||||||
@ -180,7 +183,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
final NodeValidationException e =
|
final NodeValidationException e =
|
||||||
expectThrows(
|
expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(check), "testHeapSizeCheck"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testHeapSizeCheck"));
|
||||||
assertThat(
|
assertThat(
|
||||||
e.getMessage(),
|
e.getMessage(),
|
||||||
containsString("initial heap size [" + initialHeapSize.get() + "] " +
|
containsString("initial heap size [" + initialHeapSize.get() + "] " +
|
||||||
@ -188,7 +191,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
initialHeapSize.set(maxHeapSize.get());
|
initialHeapSize.set(maxHeapSize.get());
|
||||||
|
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testHeapSizeCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testHeapSizeCheck");
|
||||||
|
|
||||||
// nothing should happen if the initial heap size or the max
|
// nothing should happen if the initial heap size or the max
|
||||||
// heap size is not available
|
// heap size is not available
|
||||||
@ -197,7 +200,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
} else {
|
} else {
|
||||||
maxHeapSize.set(0);
|
maxHeapSize.set(0);
|
||||||
}
|
}
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testHeapSizeCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testHeapSizeCheck");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFileDescriptorLimits() throws NodeValidationException {
|
public void testFileDescriptorLimits() throws NodeValidationException {
|
||||||
@ -223,17 +226,17 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e =
|
final NodeValidationException e =
|
||||||
expectThrows(NodeValidationException.class,
|
expectThrows(NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(check), "testFileDescriptorLimits"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testFileDescriptorLimits"));
|
||||||
assertThat(e.getMessage(), containsString("max file descriptors"));
|
assertThat(e.getMessage(), containsString("max file descriptors"));
|
||||||
|
|
||||||
maxFileDescriptorCount.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
|
maxFileDescriptorCount.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
|
||||||
|
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testFileDescriptorLimits");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testFileDescriptorLimits");
|
||||||
|
|
||||||
// nothing should happen if current file descriptor count is
|
// nothing should happen if current file descriptor count is
|
||||||
// not available
|
// not available
|
||||||
maxFileDescriptorCount.set(-1);
|
maxFileDescriptorCount.set(-1);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testFileDescriptorLimits");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testFileDescriptorLimits");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFileDescriptorLimitsThrowsOnInvalidLimit() {
|
public void testFileDescriptorLimitsThrowsOnInvalidLimit() {
|
||||||
@ -266,17 +269,19 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
testCases.add(new MlockallCheckTestCase(false, false, false));
|
testCases.add(new MlockallCheckTestCase(false, false, false));
|
||||||
|
|
||||||
for (final MlockallCheckTestCase testCase : testCases) {
|
for (final MlockallCheckTestCase testCase : testCases) {
|
||||||
final BootstrapChecks.MlockallCheck check = new BootstrapChecks.MlockallCheck(testCase.mlockallSet) {
|
final BootstrapChecks.MlockallCheck check = new BootstrapChecks.MlockallCheck() {
|
||||||
@Override
|
@Override
|
||||||
boolean isMemoryLocked() {
|
boolean isMemoryLocked() {
|
||||||
return testCase.isMemoryLocked;
|
return testCase.isMemoryLocked;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
BootstrapContext bootstrapContext = new BootstrapContext(
|
||||||
|
Settings.builder().put("bootstrap.memory_lock", testCase.mlockallSet).build(), null);
|
||||||
if (testCase.shouldFail) {
|
if (testCase.shouldFail) {
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(
|
() -> BootstrapChecks.check(
|
||||||
|
bootstrapContext,
|
||||||
true,
|
true,
|
||||||
Collections.singletonList(check),
|
Collections.singletonList(check),
|
||||||
"testFileDescriptorLimitsThrowsOnInvalidLimit"));
|
"testFileDescriptorLimitsThrowsOnInvalidLimit"));
|
||||||
@ -285,7 +290,8 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
containsString("memory locking requested for elasticsearch process but memory is not locked"));
|
containsString("memory locking requested for elasticsearch process but memory is not locked"));
|
||||||
} else {
|
} else {
|
||||||
// nothing should happen
|
// nothing should happen
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testFileDescriptorLimitsThrowsOnInvalidLimit");
|
BootstrapChecks.check(bootstrapContext, true, Collections.singletonList(check),
|
||||||
|
"testFileDescriptorLimitsThrowsOnInvalidLimit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -302,17 +308,17 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck"));
|
||||||
assertThat(e.getMessage(), containsString("max number of threads"));
|
assertThat(e.getMessage(), containsString("max number of threads"));
|
||||||
|
|
||||||
maxNumberOfThreads.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
|
maxNumberOfThreads.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
|
||||||
|
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck");
|
||||||
|
|
||||||
// nothing should happen if current max number of threads is
|
// nothing should happen if current max number of threads is
|
||||||
// not available
|
// not available
|
||||||
maxNumberOfThreads.set(-1);
|
maxNumberOfThreads.set(-1);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxNumberOfThreadsCheck");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMaxSizeVirtualMemory() throws NodeValidationException {
|
public void testMaxSizeVirtualMemory() throws NodeValidationException {
|
||||||
@ -332,16 +338,16 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(check), "testMaxSizeVirtualMemory"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxSizeVirtualMemory"));
|
||||||
assertThat(e.getMessage(), containsString("max size virtual memory"));
|
assertThat(e.getMessage(), containsString("max size virtual memory"));
|
||||||
|
|
||||||
maxSizeVirtualMemory.set(rlimInfinity);
|
maxSizeVirtualMemory.set(rlimInfinity);
|
||||||
|
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testMaxSizeVirtualMemory");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxSizeVirtualMemory");
|
||||||
|
|
||||||
// nothing should happen if max size virtual memory is not available
|
// nothing should happen if max size virtual memory is not available
|
||||||
maxSizeVirtualMemory.set(Long.MIN_VALUE);
|
maxSizeVirtualMemory.set(Long.MIN_VALUE);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testMaxSizeVirtualMemory");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxSizeVirtualMemory");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMaxFileSizeCheck() throws NodeValidationException {
|
public void testMaxFileSizeCheck() throws NodeValidationException {
|
||||||
@ -361,16 +367,16 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(check), "testMaxFileSize"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxFileSize"));
|
||||||
assertThat(e.getMessage(), containsString("max file size"));
|
assertThat(e.getMessage(), containsString("max file size"));
|
||||||
|
|
||||||
maxFileSize.set(rlimInfinity);
|
maxFileSize.set(rlimInfinity);
|
||||||
|
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testMaxFileSize");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxFileSize");
|
||||||
|
|
||||||
// nothing should happen if max file size is not available
|
// nothing should happen if max file size is not available
|
||||||
maxFileSize.set(Long.MIN_VALUE);
|
maxFileSize.set(Long.MIN_VALUE);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testMaxFileSize");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxFileSize");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMaxMapCountCheck() throws NodeValidationException {
|
public void testMaxMapCountCheck() throws NodeValidationException {
|
||||||
@ -385,17 +391,17 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(check), "testMaxMapCountCheck"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxMapCountCheck"));
|
||||||
assertThat(e.getMessage(), containsString("max virtual memory areas vm.max_map_count"));
|
assertThat(e.getMessage(), containsString("max virtual memory areas vm.max_map_count"));
|
||||||
|
|
||||||
maxMapCount.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
|
maxMapCount.set(randomIntBetween(limit + 1, Integer.MAX_VALUE));
|
||||||
|
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testMaxMapCountCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxMapCountCheck");
|
||||||
|
|
||||||
// nothing should happen if current vm.max_map_count is not
|
// nothing should happen if current vm.max_map_count is not
|
||||||
// available
|
// available
|
||||||
maxMapCount.set(-1);
|
maxMapCount.set(-1);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testMaxMapCountCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testMaxMapCountCheck");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testClientJvmCheck() throws NodeValidationException {
|
public void testClientJvmCheck() throws NodeValidationException {
|
||||||
@ -409,14 +415,14 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(check), "testClientJvmCheck"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testClientJvmCheck"));
|
||||||
assertThat(
|
assertThat(
|
||||||
e.getMessage(),
|
e.getMessage(),
|
||||||
containsString("JVM is using the client VM [Java HotSpot(TM) 32-Bit Client VM] " +
|
containsString("JVM is using the client VM [Java HotSpot(TM) 32-Bit Client VM] " +
|
||||||
"but should be using a server VM for the best performance"));
|
"but should be using a server VM for the best performance"));
|
||||||
|
|
||||||
vmName.set("Java HotSpot(TM) 32-Bit Server VM");
|
vmName.set("Java HotSpot(TM) 32-Bit Server VM");
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testClientJvmCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testClientJvmCheck");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUseSerialGCCheck() throws NodeValidationException {
|
public void testUseSerialGCCheck() throws NodeValidationException {
|
||||||
@ -430,19 +436,22 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(check), "testUseSerialGCCheck"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testUseSerialGCCheck"));
|
||||||
assertThat(
|
assertThat(
|
||||||
e.getMessage(),
|
e.getMessage(),
|
||||||
containsString("JVM is using the serial collector but should not be for the best performance; " + "" +
|
containsString("JVM is using the serial collector but should not be for the best performance; " + "" +
|
||||||
"either it's the default for the VM [" + JvmInfo.jvmInfo().getVmName() +"] or -XX:+UseSerialGC was explicitly specified"));
|
"either it's the default for the VM [" + JvmInfo.jvmInfo().getVmName() +"] or -XX:+UseSerialGC was explicitly specified"));
|
||||||
|
|
||||||
useSerialGC.set("false");
|
useSerialGC.set("false");
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), "testUseSerialGCCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), "testUseSerialGCCheck");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSystemCallFilterCheck() throws NodeValidationException {
|
public void testSystemCallFilterCheck() throws NodeValidationException {
|
||||||
final AtomicBoolean isSystemCallFilterInstalled = new AtomicBoolean();
|
final AtomicBoolean isSystemCallFilterInstalled = new AtomicBoolean();
|
||||||
final BootstrapChecks.SystemCallFilterCheck systemCallFilterEnabledCheck = new BootstrapChecks.SystemCallFilterCheck(true) {
|
BootstrapContext context = randomBoolean() ? new BootstrapContext(Settings.builder().put("bootstrap.system_call_filter", true)
|
||||||
|
.build(), null) : defaultContext;
|
||||||
|
|
||||||
|
final BootstrapChecks.SystemCallFilterCheck systemCallFilterEnabledCheck = new BootstrapChecks.SystemCallFilterCheck() {
|
||||||
@Override
|
@Override
|
||||||
boolean isSystemCallFilterInstalled() {
|
boolean isSystemCallFilterInstalled() {
|
||||||
return isSystemCallFilterInstalled.get();
|
return isSystemCallFilterInstalled.get();
|
||||||
@ -451,25 +460,26 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(systemCallFilterEnabledCheck), "testSystemCallFilterCheck"));
|
() -> BootstrapChecks.check(context, true, Collections.singletonList(systemCallFilterEnabledCheck),
|
||||||
|
"testSystemCallFilterCheck"));
|
||||||
assertThat(
|
assertThat(
|
||||||
e.getMessage(),
|
e.getMessage(),
|
||||||
containsString("system call filters failed to install; " +
|
containsString("system call filters failed to install; " +
|
||||||
"check the logs and fix your configuration or disable system call filters at your own risk"));
|
"check the logs and fix your configuration or disable system call filters at your own risk"));
|
||||||
|
|
||||||
isSystemCallFilterInstalled.set(true);
|
isSystemCallFilterInstalled.set(true);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(systemCallFilterEnabledCheck), "testSystemCallFilterCheck");
|
BootstrapChecks.check(context, true, Collections.singletonList(systemCallFilterEnabledCheck), "testSystemCallFilterCheck");
|
||||||
|
BootstrapContext context_1 = new BootstrapContext(Settings.builder().put("bootstrap.system_call_filter", false).build(), null);
|
||||||
final BootstrapChecks.SystemCallFilterCheck systemCallFilterNotEnabledCheck = new BootstrapChecks.SystemCallFilterCheck(false) {
|
final BootstrapChecks.SystemCallFilterCheck systemCallFilterNotEnabledCheck = new BootstrapChecks.SystemCallFilterCheck() {
|
||||||
@Override
|
@Override
|
||||||
boolean isSystemCallFilterInstalled() {
|
boolean isSystemCallFilterInstalled() {
|
||||||
return isSystemCallFilterInstalled.get();
|
return isSystemCallFilterInstalled.get();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
isSystemCallFilterInstalled.set(false);
|
isSystemCallFilterInstalled.set(false);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(systemCallFilterNotEnabledCheck), "testSystemCallFilterCheck");
|
BootstrapChecks.check(context_1, true, Collections.singletonList(systemCallFilterNotEnabledCheck), "testSystemCallFilterCheck");
|
||||||
isSystemCallFilterInstalled.set(true);
|
isSystemCallFilterInstalled.set(true);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(systemCallFilterNotEnabledCheck), "testSystemCallFilterCheck");
|
BootstrapChecks.check(context_1, true, Collections.singletonList(systemCallFilterNotEnabledCheck), "testSystemCallFilterCheck");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMightForkCheck() throws NodeValidationException {
|
public void testMightForkCheck() throws NodeValidationException {
|
||||||
@ -573,13 +583,13 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
} else {
|
} else {
|
||||||
enableMightFork.run();
|
enableMightFork.run();
|
||||||
}
|
}
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), methodName);
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), methodName);
|
||||||
|
|
||||||
// if system call filter is enabled, but we will not fork, nothing should
|
// if system call filter is enabled, but we will not fork, nothing should
|
||||||
// happen
|
// happen
|
||||||
isSystemCallFilterInstalled.set(true);
|
isSystemCallFilterInstalled.set(true);
|
||||||
disableMightFork.run();
|
disableMightFork.run();
|
||||||
BootstrapChecks.check(true, Collections.singletonList(check), methodName);
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(check), methodName);
|
||||||
|
|
||||||
// if system call filter is enabled, and we might fork, the check should be enforced, regardless of bootstrap checks being enabled
|
// if system call filter is enabled, and we might fork, the check should be enforced, regardless of bootstrap checks being enabled
|
||||||
// or not
|
// or not
|
||||||
@ -588,7 +598,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(randomBoolean(), Collections.singletonList(check), methodName));
|
() -> BootstrapChecks.check(defaultContext, randomBoolean(), Collections.singletonList(check), methodName));
|
||||||
consumer.accept(e);
|
consumer.accept(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,7 +623,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> {
|
() -> {
|
||||||
BootstrapChecks.check(true, checks, "testEarlyAccessCheck");
|
BootstrapChecks.check(defaultContext, true, checks, "testEarlyAccessCheck");
|
||||||
});
|
});
|
||||||
assertThat(
|
assertThat(
|
||||||
e.getMessage(),
|
e.getMessage(),
|
||||||
@ -624,7 +634,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
// if not on an early-access build, nothing should happen
|
// if not on an early-access build, nothing should happen
|
||||||
javaVersion.set(randomFrom("1.8.0_152", "9"));
|
javaVersion.set(randomFrom("1.8.0_152", "9"));
|
||||||
BootstrapChecks.check(true, checks, "testEarlyAccessCheck");
|
BootstrapChecks.check(defaultContext, true, checks, "testEarlyAccessCheck");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,7 +670,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
final NodeValidationException e =
|
final NodeValidationException e =
|
||||||
expectThrows(
|
expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(true, Collections.singletonList(g1GCCheck), "testG1GCCheck"));
|
() -> BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck), "testG1GCCheck"));
|
||||||
assertThat(
|
assertThat(
|
||||||
e.getMessage(),
|
e.getMessage(),
|
||||||
containsString(
|
containsString(
|
||||||
@ -668,12 +678,12 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
// if G1GC is disabled, nothing should happen
|
// if G1GC is disabled, nothing should happen
|
||||||
isG1GCEnabled.set(false);
|
isG1GCEnabled.set(false);
|
||||||
BootstrapChecks.check(true, Collections.singletonList(g1GCCheck), "testG1GCCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck), "testG1GCCheck");
|
||||||
|
|
||||||
// if on or after update 40, nothing should happen independent of whether or not G1GC is enabled
|
// if on or after update 40, nothing should happen independent of whether or not G1GC is enabled
|
||||||
isG1GCEnabled.set(randomBoolean());
|
isG1GCEnabled.set(randomBoolean());
|
||||||
jvmVersion.set(String.format(Locale.ROOT, "25.%d-b%d", randomIntBetween(40, 112), randomIntBetween(1, 128)));
|
jvmVersion.set(String.format(Locale.ROOT, "25.%d-b%d", randomIntBetween(40, 112), randomIntBetween(1, 128)));
|
||||||
BootstrapChecks.check(true, Collections.singletonList(g1GCCheck), "testG1GCCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(g1GCCheck), "testG1GCCheck");
|
||||||
|
|
||||||
final BootstrapChecks.G1GCCheck nonOracleCheck = new BootstrapChecks.G1GCCheck() {
|
final BootstrapChecks.G1GCCheck nonOracleCheck = new BootstrapChecks.G1GCCheck() {
|
||||||
|
|
||||||
@ -685,7 +695,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// if not on an Oracle JVM, nothing should happen
|
// if not on an Oracle JVM, nothing should happen
|
||||||
BootstrapChecks.check(true, Collections.singletonList(nonOracleCheck), "testG1GCCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(nonOracleCheck), "testG1GCCheck");
|
||||||
|
|
||||||
final BootstrapChecks.G1GCCheck nonJava8Check = new BootstrapChecks.G1GCCheck() {
|
final BootstrapChecks.G1GCCheck nonJava8Check = new BootstrapChecks.G1GCCheck() {
|
||||||
|
|
||||||
@ -697,13 +707,13 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// if not Java 8, nothing should happen
|
// if not Java 8, nothing should happen
|
||||||
BootstrapChecks.check(true, Collections.singletonList(nonJava8Check), "testG1GCCheck");
|
BootstrapChecks.check(defaultContext, true, Collections.singletonList(nonJava8Check), "testG1GCCheck");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAlwaysEnforcedChecks() {
|
public void testAlwaysEnforcedChecks() {
|
||||||
final BootstrapCheck check = new BootstrapCheck() {
|
final BootstrapCheck check = new BootstrapCheck() {
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,7 +730,7 @@ public class BootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException alwaysEnforced = expectThrows(
|
final NodeValidationException alwaysEnforced = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(randomBoolean(), Collections.singletonList(check), "testAlwaysEnforcedChecks"));
|
() -> BootstrapChecks.check(defaultContext, randomBoolean(), Collections.singletonList(check), "testAlwaysEnforcedChecks"));
|
||||||
assertThat(alwaysEnforced, hasToString(containsString("error")));
|
assertThat(alwaysEnforced, hasToString(containsString("error")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import org.apache.lucene.util.LuceneTestCase;
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||||
|
import org.elasticsearch.bootstrap.BootstrapContext;
|
||||||
import org.elasticsearch.cluster.ClusterName;
|
import org.elasticsearch.cluster.ClusterName;
|
||||||
import org.elasticsearch.common.network.NetworkModule;
|
import org.elasticsearch.common.network.NetworkModule;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
@ -66,7 +67,7 @@ public class NodeTests extends ESTestCase {
|
|||||||
public static class CheckPlugin extends Plugin {
|
public static class CheckPlugin extends Plugin {
|
||||||
public static final BootstrapCheck CHECK = new BootstrapCheck() {
|
public static final BootstrapCheck CHECK = new BootstrapCheck() {
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ public class NodeTests extends ESTestCase {
|
|||||||
AtomicBoolean executed = new AtomicBoolean(false);
|
AtomicBoolean executed = new AtomicBoolean(false);
|
||||||
try (Node node = new MockNode(settings.build(), Arrays.asList(getTestTransportPlugin(), CheckPlugin.class)) {
|
try (Node node = new MockNode(settings.build(), Arrays.asList(getTestTransportPlugin(), CheckPlugin.class)) {
|
||||||
@Override
|
@Override
|
||||||
protected void validateNodeBeforeAcceptingRequests(Settings settings, BoundTransportAddress boundTransportAddress,
|
protected void validateNodeBeforeAcceptingRequests(BootstrapContext context, BoundTransportAddress boundTransportAddress,
|
||||||
List<BootstrapCheck> bootstrapChecks) throws NodeValidationException {
|
List<BootstrapCheck> bootstrapChecks) throws NodeValidationException {
|
||||||
assertEquals(1, bootstrapChecks.size());
|
assertEquals(1, bootstrapChecks.size());
|
||||||
assertSame(CheckPlugin.CHECK, bootstrapChecks.get(0));
|
assertSame(CheckPlugin.CHECK, bootstrapChecks.get(0));
|
||||||
|
@ -21,6 +21,7 @@ package org.elasticsearch.bootstrap;
|
|||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.elasticsearch.common.SuppressForbidden;
|
import org.elasticsearch.common.SuppressForbidden;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.node.NodeValidationException;
|
import org.elasticsearch.node.NodeValidationException;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
import org.hamcrest.Matcher;
|
import org.hamcrest.Matcher;
|
||||||
@ -61,7 +62,7 @@ public class EvilBootstrapChecksTests extends ESTestCase {
|
|||||||
final List<BootstrapCheck> checks = Collections.singletonList(
|
final List<BootstrapCheck> checks = Collections.singletonList(
|
||||||
new BootstrapCheck() {
|
new BootstrapCheck() {
|
||||||
@Override
|
@Override
|
||||||
public boolean check() {
|
public boolean check(BootstrapContext context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ public class EvilBootstrapChecksTests extends ESTestCase {
|
|||||||
|
|
||||||
final NodeValidationException e = expectThrows(
|
final NodeValidationException e = expectThrows(
|
||||||
NodeValidationException.class,
|
NodeValidationException.class,
|
||||||
() -> BootstrapChecks.check(false, checks, logger));
|
() -> BootstrapChecks.check(new BootstrapContext(Settings.EMPTY, null), false, checks, logger));
|
||||||
final Matcher<String> allOf =
|
final Matcher<String> allOf =
|
||||||
allOf(containsString("bootstrap checks failed"), containsString("error"));
|
allOf(containsString("bootstrap checks failed"), containsString("error"));
|
||||||
assertThat(e, hasToString(allOf));
|
assertThat(e, hasToString(allOf));
|
||||||
@ -87,7 +88,7 @@ public class EvilBootstrapChecksTests extends ESTestCase {
|
|||||||
setEsEnforceBootstrapChecks(null);
|
setEsEnforceBootstrapChecks(null);
|
||||||
final Logger logger = mock(Logger.class);
|
final Logger logger = mock(Logger.class);
|
||||||
// nothing should happen
|
// nothing should happen
|
||||||
BootstrapChecks.check(false, emptyList(), logger);
|
BootstrapChecks.check(new BootstrapContext(Settings.EMPTY, null), false, emptyList(), logger);
|
||||||
verifyNoMoreInteractions(logger);
|
verifyNoMoreInteractions(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ public class EvilBootstrapChecksTests extends ESTestCase {
|
|||||||
final boolean enforceLimits = randomBoolean();
|
final boolean enforceLimits = randomBoolean();
|
||||||
final IllegalArgumentException e = expectThrows(
|
final IllegalArgumentException e = expectThrows(
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> BootstrapChecks.check(enforceLimits, emptyList(), "testInvalidValue"));
|
() -> BootstrapChecks.check(new BootstrapContext(Settings.EMPTY, null), enforceLimits, emptyList(), "testInvalidValue"));
|
||||||
final Matcher<String> matcher = containsString(
|
final Matcher<String> matcher = containsString(
|
||||||
"[es.enforce.bootstrap.checks] must be [true] but was [" + value + "]");
|
"[es.enforce.bootstrap.checks] must be [true] but was [" + value + "]");
|
||||||
assertThat(e, hasToString(matcher));
|
assertThat(e, hasToString(matcher));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user