diff --git a/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java b/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java index c72bf894457..744e654706c 100644 --- a/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java +++ b/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java @@ -654,9 +654,8 @@ public class LicensesService extends AbstractLifecycleComponent @Override public void run() { - if (logger.isTraceEnabled()) { - logger.trace("Performing LicensingClientNotificationJob"); - } + logger.info("Performing LicensingClientNotificationJob"); + // next clusterChanged event will deal with the missed notifications if (!clusterService.state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) { @@ -669,6 +668,8 @@ public class LicensesService extends AbstractLifecycleComponent logger.info("Reschedule licensing client notification job was rejected", ex); } } + } else { + logger.info("skip notification [STATE_NOT_RECOVERED_BLOCK]"); } } } diff --git a/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java b/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java index a1beacb4b7c..34c74f3fa65 100644 --- a/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java +++ b/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java @@ -10,19 +10,24 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ProcessedClusterStateUpdateTask; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.base.Predicate; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.core.ESLicense; import org.elasticsearch.license.licensor.ESLicenseSigner; +import org.elasticsearch.license.plugin.core.LicensesManagerService; import org.elasticsearch.license.plugin.core.LicensesMetaData; import org.elasticsearch.test.ElasticsearchIntegrationTest; +import org.elasticsearch.test.InternalTestCluster; import java.util.UUID; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import static org.elasticsearch.license.AbstractLicensingTestBase.getTestPriKeyPath; import static org.elasticsearch.license.AbstractLicensingTestBase.getTestPubKeyPath; +import static org.hamcrest.CoreMatchers.equalTo; /** */ @@ -82,4 +87,57 @@ public abstract class AbstractLicensesIntegrationTests extends ElasticsearchInte ESLicenseSigner signer = new ESLicenseSigner(getTestPriKeyPath(), getTestPubKeyPath()); return signer.sign(licenseSpec); } + + protected void assertLicenseManagerEnabledFeatureFor(final String feature) throws InterruptedException { + assertLicenseManagerStatusFor(feature, true); + } + + protected void assertLicenseManagerDisabledFeatureFor(final String feature) throws InterruptedException { + assertLicenseManagerStatusFor(feature, false); + } + + protected void assertLicenseManagerStatusFor(final String feature, final boolean expectedEnabled) throws InterruptedException { + assertThat(awaitBusy(new Predicate() { + @Override + public boolean apply(Object o) { + for (LicensesManagerService managerService : licensesManagerServices()) { + if (expectedEnabled != managerService.enabledFeatures().contains(feature)) { + return false; + } + } + return true; + } + }, 2, TimeUnit.SECONDS), equalTo(true)); + } + + protected void assertConsumerPluginDisableNotification(int timeoutInSec) throws InterruptedException { + assertConsumerPluginNotification(false, timeoutInSec); + } + protected void assertConsumerPluginEnableNotification(int timeoutInSec) throws InterruptedException { + assertConsumerPluginNotification(true, timeoutInSec); + } + + protected void assertConsumerPluginNotification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException { + assertThat(awaitBusy(new Predicate() { + @Override + public boolean apply(Object o) { + for (TestPluginService pluginService : consumerPluginServices()) { + if (expectedEnabled != pluginService.enabled()) { + return false; + } + } + return true; + } + }, timeoutInSec, TimeUnit.SECONDS), equalTo(true)); + } + + private Iterable consumerPluginServices() { + final InternalTestCluster clients = internalCluster(); + return clients.getDataNodeInstances(TestPluginService.class); + } + + private Iterable licensesManagerServices() { + final InternalTestCluster clients = internalCluster(); + return clients.getDataNodeInstances(LicensesManagerService.class); + } } diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java b/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java index 7596a7385a5..2eba2fd936b 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java +++ b/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java @@ -124,58 +124,6 @@ public class LicensesPluginIntegrationTests extends AbstractLicensesIntegrationT assertLicenseManagerDisabledFeatureFor(TestPluginService.FEATURE_NAME); } - private void assertLicenseManagerEnabledFeatureFor(final String feature) throws InterruptedException { - assertLicenseManagerStatusFor(feature, true); - } - - private void assertLicenseManagerDisabledFeatureFor(final String feature) throws InterruptedException { - assertLicenseManagerStatusFor(feature, false); - } - - private void assertLicenseManagerStatusFor(final String feature, final boolean expectedEnabled) throws InterruptedException { - assertThat(awaitBusy(new Predicate() { - @Override - public boolean apply(Object o) { - for (LicensesManagerService managerService : licensesManagerServices()) { - if (expectedEnabled != managerService.enabledFeatures().contains(feature)) { - return false; - } - } - return true; - } - }, 2, TimeUnit.SECONDS), equalTo(true)); - } - - private void assertConsumerPluginDisableNotification(int timeoutInSec) throws InterruptedException { - assertConsumerPluginNotification(false, timeoutInSec); - } - private void assertConsumerPluginEnableNotification(int timeoutInSec) throws InterruptedException { - assertConsumerPluginNotification(true, timeoutInSec); - } - - private void assertConsumerPluginNotification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException { - assertThat(awaitBusy(new Predicate() { - @Override - public boolean apply(Object o) { - for (TestPluginService pluginService : consumerPluginServices()) { - if (expectedEnabled != pluginService.enabled()) { - return false; - } - } - return true; - } - }, timeoutInSec, TimeUnit.SECONDS), equalTo(true)); - } - - private Iterable consumerPluginServices() { - final InternalTestCluster clients = internalCluster(); - return clients.getDataNodeInstances(TestPluginService.class); - } - - private Iterable licensesManagerServices() { - final InternalTestCluster clients = internalCluster(); - return clients.getDataNodeInstances(LicensesManagerService.class); - } private LicensesManagerService masterLicenseManagerService() { final InternalTestCluster clients = internalCluster(); diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterRestartTest.java b/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterRestartTest.java index b5c8932176a..096834b7f38 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterRestartTest.java +++ b/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterRestartTest.java @@ -16,7 +16,9 @@ import org.elasticsearch.license.plugin.action.get.GetLicenseResponse; import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder; import org.elasticsearch.license.plugin.action.put.PutLicenseResponse; import org.elasticsearch.license.plugin.core.LicensesStatus; +import org.elasticsearch.node.internal.InternalNode; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import java.util.Arrays; @@ -26,7 +28,7 @@ import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; import static org.hamcrest.CoreMatchers.equalTo; -@ClusterScope(scope = TEST, numDataNodes = 0) +@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0) public class LicensesServiceClusterRestartTest extends AbstractLicensesIntegrationTests { @Override @@ -36,11 +38,19 @@ public class LicensesServiceClusterRestartTest extends AbstractLicensesIntegrati @Override protected Settings nodeSettings(int nodeOrdinal) { + return nodeSettingsBuilder(nodeOrdinal).build(); + } + + private ImmutableSettings.Builder nodeSettingsBuilder(int nodeOrdinal) { return ImmutableSettings.settingsBuilder() - .put(super.nodeSettings(nodeOrdinal)) + //.put(super.nodeSettings(nodeOrdinal)) .put("gateway.type", "local") + .put("plugins.load_classpath_plugins", false) + .put("node.data", true) .put("format", "json") - .build(); + .put("test_consumer_plugin.trial_license_duration_in_seconds", 5) + .putArray("plugin.types", LicensePlugin.class.getName(), TestConsumerPlugin.class.getName()) + .put(InternalNode.HTTP_ENABLED, true); } @Before @@ -48,12 +58,11 @@ public class LicensesServiceClusterRestartTest extends AbstractLicensesIntegrati wipeAllLicenses(); } - @Test + @Test @Ignore public void testClusterRestart() throws Exception { logger.info("--> starting 1 node"); - internalCluster().startNode(); + internalCluster().startNode(nodeSettingsBuilder(0)); ensureGreen(); - wipeAllLicenses(); final List esLicenses = generateAndPutLicense(); getAndCheckLicense(esLicenses); @@ -64,6 +73,34 @@ public class LicensesServiceClusterRestartTest extends AbstractLicensesIntegrati getAndCheckLicense(esLicenses); } + @Test + public void testClusterNotRecovered() throws Exception { + + logger.info("--> start 1 node (should not recover)"); + internalCluster().startNode(nodeSettingsBuilder(0).put("gateway.recover_after_nodes", 3)); + assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME); + assertConsumerPluginEnableNotification(1); + + internalCluster().startNode(nodeSettingsBuilder(1).put("gateway.recover_after_nodes", 3)); + assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME); + assertConsumerPluginEnableNotification(1); + + internalCluster().startNode(nodeSettingsBuilder(2).put("gateway.recover_after_nodes", 3)); + assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME); + assertConsumerPluginEnableNotification(1); + + internalCluster().stopRandomNonMasterNode(); + // sleep for the entire trial license duration + assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME); + assertConsumerPluginEnableNotification(1); + + Thread.sleep(5 * 1050l); + internalCluster().startNode(nodeSettingsBuilder(3).put("gateway.recover_after_nodes", 3)); + assertLicenseManagerDisabledFeatureFor(TestPluginService.FEATURE_NAME); + assertConsumerPluginDisableNotification(1); + + } + private List generateAndPutLicense() throws Exception { ClusterAdminClient cluster = internalCluster().client().admin().cluster(); ESLicense license = generateSignedLicense("shield", TimeValue.timeValueMinutes(1));