Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove rolling restart checks for x-pack #95428

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.elasticsearch.protocol.xpack.license.LicensesStatus;
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;

import java.time.Clock;
Expand Down Expand Up @@ -239,7 +238,6 @@ protected PutLicenseResponse newResponse(boolean acknowledged) {

@Override
public ClusterState execute(ClusterState currentState) throws Exception {
XPackPlugin.checkReadyForXPackCustomMetadata(currentState);
final Version oldestNodeVersion = currentState.nodes().getSmallestNonClientNodeVersion();
if (licenseIsCompatible(newLicense, oldestNodeVersion) == false) {
throw new IllegalStateException(
Expand Down Expand Up @@ -378,8 +376,7 @@ protected void doStart() throws ElasticsearchException {
if (clusterService.lifecycleState() == Lifecycle.State.STARTED) {
final ClusterState clusterState = clusterService.state();
if (clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) == false
&& clusterState.nodes().getMasterNode() != null
&& XPackPlugin.isReadyForXPackCustomMetadata(clusterState)) {
&& clusterState.nodes().getMasterNode() != null) {
final LicensesMetadata currentMetadata = clusterState.metadata().custom(LicensesMetadata.TYPE);
boolean noLicense = currentMetadata == null || currentMetadata.getLicense() == null;
if (clusterState.getNodes().isLocalNodeElectedMaster()
Expand Down Expand Up @@ -411,14 +408,6 @@ public void clusterChanged(ClusterChangedEvent event) {
final ClusterState previousClusterState = event.previousState();
final ClusterState currentClusterState = event.state();
if (currentClusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) == false) {
if (XPackPlugin.isReadyForXPackCustomMetadata(currentClusterState) == false) {
logger.debug(
"cannot add license to cluster as the following nodes might not understand the license metadata: {}",
() -> XPackPlugin.nodesNotReadyForXPackCustomMetadata(currentClusterState)
);
return;
}

final LicensesMetadata prevLicensesMetadata = previousClusterState.getMetadata().custom(LicensesMetadata.TYPE);
final LicensesMetadata currentLicensesMetadata = currentClusterState.getMetadata().custom(LicensesMetadata.TYPE);
// notify all interested plugins
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.xpack.core.XPackPlugin;

import java.time.Clock;
import java.util.Map;
Expand Down Expand Up @@ -124,7 +123,6 @@ static class Executor implements ClusterStateTaskExecutor<StartBasicClusterTask>
@Override
public ClusterState execute(BatchExecutionContext<StartBasicClusterTask> batchExecutionContext) throws Exception {
final var initialState = batchExecutionContext.initialState();
XPackPlugin.checkReadyForXPackCustomMetadata(initialState);
final LicensesMetadata originalLicensesMetadata = initialState.metadata().custom(LicensesMetadata.TYPE);
var currentLicensesMetadata = originalLicensesMetadata;
for (final var taskContext : batchExecutionContext.taskContexts()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.xpack.core.XPackPlugin;

import java.time.Clock;
import java.util.Collections;
Expand Down Expand Up @@ -110,7 +109,6 @@ static class Executor implements ClusterStateTaskExecutor<StartTrialClusterTask>
@Override
public ClusterState execute(BatchExecutionContext<StartTrialClusterTask> batchExecutionContext) throws Exception {
final var initialState = batchExecutionContext.initialState();
XPackPlugin.checkReadyForXPackCustomMetadata(initialState);
final LicensesMetadata originalLicensesMetadata = initialState.metadata().custom(LicensesMetadata.TYPE);
var currentLicensesMetadata = originalLicensesMetadata;
for (final var taskContext : batchExecutionContext.taskContexts()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.xpack.core.XPackPlugin;

import java.time.Clock;
import java.util.UUID;
Expand Down Expand Up @@ -51,7 +50,6 @@ public void clusterStateProcessed(ClusterState oldState, ClusterState newState)

@Override
public ClusterState execute(ClusterState currentState) throws Exception {
XPackPlugin.checkReadyForXPackCustomMetadata(currentState);
final Metadata metadata = currentState.metadata();
final LicensesMetadata currentLicensesMetadata = metadata.custom(LicensesMetadata.TYPE);
// do not generate a license if any license is present
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
import org.elasticsearch.action.support.ActionFilter;
import org.elasticsearch.action.support.TransportAction;
import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.routing.allocation.AllocationService;
Expand All @@ -35,7 +33,6 @@
import org.elasticsearch.common.settings.SettingsFilter;
import org.elasticsearch.common.ssl.SslConfiguration;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.core.Booleans;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.NodeEnvironment;
import org.elasticsearch.index.IndexSettingProvider;
Expand All @@ -48,7 +45,6 @@
import org.elasticsearch.license.LicenseService;
import org.elasticsearch.license.LicenseSettings;
import org.elasticsearch.license.LicenseUtils;
import org.elasticsearch.license.LicensesMetadata;
import org.elasticsearch.license.Licensing;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.license.internal.MutableLicenseService;
Expand Down Expand Up @@ -87,18 +83,14 @@
import org.elasticsearch.xpack.core.action.XPackUsageResponse;
import org.elasticsearch.xpack.core.async.DeleteAsyncResultAction;
import org.elasticsearch.xpack.core.async.TransportDeleteAsyncResultAction;
import org.elasticsearch.xpack.core.ml.MlMetadata;
import org.elasticsearch.xpack.core.rest.action.RestReloadAnalyzersAction;
import org.elasticsearch.xpack.core.rest.action.RestXPackInfoAction;
import org.elasticsearch.xpack.core.rest.action.RestXPackUsageAction;
import org.elasticsearch.xpack.core.security.authc.TokenMetadata;
import org.elasticsearch.xpack.core.ssl.SSLConfigurationReloader;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.elasticsearch.xpack.core.termsenum.action.TermsEnumAction;
import org.elasticsearch.xpack.core.termsenum.action.TransportTermsEnumAction;
import org.elasticsearch.xpack.core.termsenum.rest.RestTermsEnumAction;
import org.elasticsearch.xpack.core.transform.TransformMetadata;
import org.elasticsearch.xpack.core.watcher.WatcherMetadata;

import java.nio.file.Files;
import java.nio.file.Path;
Expand All @@ -113,7 +105,6 @@
import java.util.Optional;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@SuppressWarnings("HiddenField")
public class XPackPlugin extends XPackClientPlugin
Expand All @@ -126,7 +117,7 @@ public class XPackPlugin extends XPackClientPlugin
private static final DeprecationLogger deprecationLogger = DeprecationLogger.getLogger(XPackPlugin.class);

public static final String ASYNC_RESULTS_INDEX = ".async-search";
public static final String XPACK_INSTALLED_NODE_ATTR = "xpack.installed";
public static final String XPACK_INSTALLED_NODE_ATTR = "xpack.installed"; // TODO: remove in 9.0
private static final Logger logger = LogManager.getLogger(XPackPlugin.class);

// TODO: clean up this library to not ask for write access to all system properties!
Expand Down Expand Up @@ -239,57 +230,6 @@ public static LongSupplier getSharedEpochMillisSupplier() {
return epochMillisSupplier.get();
}

/**
* Checks if the cluster state allows this node to add x-pack metadata to the cluster state,
* and throws an exception otherwise.
* This check should be called before installing any x-pack metadata to the cluster state,
* to ensure that the other nodes that are part of the cluster will be able to deserialize
* that metadata. Note that if the cluster state already contains x-pack metadata, this
* check assumes that the nodes are already ready to receive additional x-pack metadata.
* Having this check properly in place everywhere allows to install x-pack into a cluster
* using a rolling restart.
*/
public static void checkReadyForXPackCustomMetadata(ClusterState clusterState) {
if (alreadyContainsXPackCustomMetadata(clusterState)) {
return;
}
List<DiscoveryNode> notReadyNodes = nodesNotReadyForXPackCustomMetadata(clusterState);
if (notReadyNodes.isEmpty() == false) {
throw new IllegalStateException("The following nodes are not ready yet for enabling x-pack custom metadata: " + notReadyNodes);
}
}

/**
* Checks if the cluster state allows this node to add x-pack metadata to the cluster state.
* See {@link #checkReadyForXPackCustomMetadata} for more details.
*/
public static boolean isReadyForXPackCustomMetadata(ClusterState clusterState) {
return alreadyContainsXPackCustomMetadata(clusterState) || nodesNotReadyForXPackCustomMetadata(clusterState).isEmpty();
}

/**
* Returns the list of nodes that won't allow this node from adding x-pack metadata to the cluster state.
* See {@link #checkReadyForXPackCustomMetadata} for more details.
*/
public static List<DiscoveryNode> nodesNotReadyForXPackCustomMetadata(ClusterState clusterState) {
// check that all nodes would be capable of deserializing newly added x-pack metadata
final List<DiscoveryNode> notReadyNodes = clusterState.nodes().stream().filter(node -> {
final String xpackInstalledAttr = node.getAttributes().getOrDefault(XPACK_INSTALLED_NODE_ATTR, "false");
return Booleans.parseBoolean(xpackInstalledAttr) == false;
}).collect(Collectors.toList());

return notReadyNodes;
}

private static boolean alreadyContainsXPackCustomMetadata(ClusterState clusterState) {
final Metadata metadata = clusterState.metadata();
return metadata.custom(LicensesMetadata.TYPE) != null
|| metadata.custom(MlMetadata.TYPE) != null
|| metadata.custom(WatcherMetadata.TYPE) != null
|| clusterState.custom(TokenMetadata.TYPE) != null
|| metadata.custom(TransformMetadata.TYPE) != null;
}

@Override
public Map<String, MetadataFieldMapper.TypeParser> getMetadataMappers() {
return Map.of(DataTierFieldMapper.NAME, DataTierFieldMapper.PARSER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@
*/
package org.elasticsearch.xpack.core;

import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.internal.Client;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.UUIDs;
import org.elasticsearch.common.component.Lifecycle;
Expand All @@ -33,14 +28,12 @@
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.core.security.authc.TokenMetadata;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.junit.Before;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static org.hamcrest.Matchers.containsString;
Expand Down Expand Up @@ -91,47 +84,6 @@ public void testXPackInstalledAttrExists() throws Exception {
assertEquals("true", xpackPlugin.additionalSettings().get("node.attr." + XPackPlugin.XPACK_INSTALLED_NODE_ATTR));
}

public void testNodesNotReadyForXPackCustomMetadata() {
boolean compatible;
boolean nodesCompatible = true;
DiscoveryNodes.Builder discoveryNodes = DiscoveryNodes.builder();

for (int i = 0; i < randomInt(3); i++) {
final Map<String, String> attributes;
if (randomBoolean()) {
attributes = Collections.singletonMap(XPackPlugin.XPACK_INSTALLED_NODE_ATTR, "true");
} else {
nodesCompatible = false;
attributes = Collections.emptyMap();
}

discoveryNodes.add(
new DiscoveryNode("node_" + i, buildNewFakeTransportAddress(), attributes, Collections.emptySet(), Version.CURRENT)
);
}
ClusterState.Builder clusterStateBuilder = ClusterState.builder(ClusterName.DEFAULT);

if (randomBoolean()) {
clusterStateBuilder.putCustom(TokenMetadata.TYPE, new TokenMetadata(Collections.emptyList(), new byte[0]));
compatible = true;
} else {
compatible = nodesCompatible;
}

ClusterState clusterState = clusterStateBuilder.nodes(discoveryNodes.build()).build();

assertEquals(XPackPlugin.nodesNotReadyForXPackCustomMetadata(clusterState).isEmpty(), nodesCompatible);
assertEquals(XPackPlugin.isReadyForXPackCustomMetadata(clusterState), compatible);

if (compatible == false) {
IllegalStateException e = expectThrows(
IllegalStateException.class,
() -> XPackPlugin.checkReadyForXPackCustomMetadata(clusterState)
);
assertThat(e.getMessage(), containsString("The following nodes are not ready yet for enabling x-pack custom metadata:"));
}
}

public void testLoadExtensions() throws Exception {
XPackPlugin xpackPlugin = createXPackPlugin(Settings.builder().build());
xpackPlugin.loadExtensions(new ExtensiblePlugin.ExtensionLoader() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xpack.core.ClientHelper;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.rollup.RollupField;
import org.elasticsearch.xpack.core.rollup.action.PutRollupJobAction;
import org.elasticsearch.xpack.core.rollup.job.RollupJob;
Expand Down Expand Up @@ -100,7 +99,6 @@ protected void masterOperation(
ClusterState clusterState,
ActionListener<AcknowledgedResponse> listener
) {
XPackPlugin.checkReadyForXPackCustomMetadata(clusterState);
checkForDeprecatedTZ(request);

FieldCapabilitiesRequest fieldCapsRequest = new FieldCapabilitiesRequest().indices(request.indices())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@
import org.elasticsearch.xcontent.XContentFactory;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xpack.core.XPackField;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.security.ScrollHelper;
import org.elasticsearch.xpack.core.security.SecurityContext;
Expand Down Expand Up @@ -2374,14 +2373,7 @@ private void initialize(ClusterService clusterService) {
}

if (state.nodes().isLocalNodeElectedMaster()) {
if (XPackPlugin.isReadyForXPackCustomMetadata(state)) {
installTokenMetadata(state);
} else {
logger.debug(
"cannot add token metadata to cluster as the following nodes might not understand the metadata: {}",
() -> XPackPlugin.nodesNotReadyForXPackCustomMetadata(state)
);
}
installTokenMetadata(state);
}

TokenMetadata custom = event.state().custom(TokenMetadata.TYPE);
Expand All @@ -2406,7 +2398,6 @@ private void installTokenMetadata(ClusterState state) {
submitUnbatchedTask("install-token-metadata", new ClusterStateUpdateTask(Priority.URGENT) {
@Override
public ClusterState execute(ClusterState currentState) {
XPackPlugin.checkReadyForXPackCustomMetadata(currentState);

if (currentState.custom(TokenMetadata.TYPE) == null) {
return ClusterState.builder(currentState).putCustom(TokenMetadata.TYPE, getTokenMetadata()).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.ClientHelper;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.security.SecurityContext;
import org.elasticsearch.xpack.core.transform.TransformMessages;
Expand Down Expand Up @@ -92,7 +91,6 @@ public TransportPutTransformAction(

@Override
protected void masterOperation(Task task, Request request, ClusterState clusterState, ActionListener<AcknowledgedResponse> listener) {
XPackPlugin.checkReadyForXPackCustomMetadata(clusterState);

TransformConfig config = request.getConfig().setCreateTime(Instant.now()).setVersion(Version.CURRENT);
config.setHeaders(getSecurityHeadersPreferringSecondary(threadPool, securityContext, clusterState));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.ActionNotFoundTransportException;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.security.SecurityContext;
import org.elasticsearch.xpack.core.transform.action.ScheduleNowTransformAction;
Expand Down Expand Up @@ -80,7 +79,6 @@ public TransportScheduleNowTransformAction(
@Override
protected void doExecute(Task task, Request request, ActionListener<Response> listener) {
final ClusterState clusterState = clusterService.state();
XPackPlugin.checkReadyForXPackCustomMetadata(clusterState);

ActionListener<TransformConfig> getTransformListener = ActionListener.wrap(unusedConfig -> {
PersistentTasksCustomMetadata.PersistentTask<?> transformTask = TransformTask.getTransformTask(request.getId(), clusterState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.security.SecurityContext;
import org.elasticsearch.xpack.core.transform.action.UpdateTransformAction;
Expand Down Expand Up @@ -99,7 +98,6 @@ public TransportUpdateTransformAction(
@Override
protected void doExecute(Task task, Request request, ActionListener<Response> listener) {
final ClusterState clusterState = clusterService.state();
XPackPlugin.checkReadyForXPackCustomMetadata(clusterState);

final DiscoveryNodes nodes = clusterState.nodes();

Expand Down
Loading