diff --git a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/DistributedJmxConnection.java b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/DistributedJmxConnection.java index 86b8ee91..bd65db6d 100644 --- a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/DistributedJmxConnection.java +++ b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/DistributedJmxConnection.java @@ -14,6 +14,7 @@ */ package com.ericsson.bss.cassandra.ecchronos.application.config.connection; +import com.ericsson.bss.cassandra.ecchronos.application.config.Config; import com.ericsson.bss.cassandra.ecchronos.application.providers.AgentJmxConnectionProvider; import com.ericsson.bss.cassandra.ecchronos.connection.DistributedJmxConnectionProvider; @@ -26,6 +27,7 @@ public class DistributedJmxConnection extends Connection { private RetryPolicyConfig myRetryPolicyConfig = new RetryPolicyConfig(); + private JolokiaConfig myJolokiaConfig = new JolokiaConfig(); public DistributedJmxConnection() { @@ -51,6 +53,18 @@ public final void setRetryPolicyConfig(final RetryPolicyConfig retryPolicyConfig myRetryPolicyConfig = retryPolicyConfig; } + @JsonProperty("jolokia") + public final JolokiaConfig getJolokiaConfig() + { + return myJolokiaConfig; + } + + @JsonProperty("jolokia") + public final void setJolokiaConfig(final JolokiaConfig jolokiaConfig) + { + myJolokiaConfig = jolokiaConfig; + } + /** * @return */ @@ -58,6 +72,7 @@ public final void setRetryPolicyConfig(final RetryPolicyConfig retryPolicyConfig protected Class[] expectedConstructor() { return new Class[] { + Config.class, Supplier.class, DistributedNativeConnectionProvider.class, EccNodesSync.class diff --git a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/JolokiaConfig.java b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/JolokiaConfig.java new file mode 100644 index 00000000..b1f3ee4d --- /dev/null +++ b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/config/connection/JolokiaConfig.java @@ -0,0 +1,72 @@ +/* + * Copyright 2024 Telefonaktiebolaget LM Ericsson + * + * Licensed 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 com.ericsson.bss.cassandra.ecchronos.application.config.connection; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Configuration class for Jolokia integration with JMX. + * This class allows enabling or disabling the Jolokia adapter and specifying the port to use. + */ +public class JolokiaConfig +{ + private static final int DEFAULT_JOLOKIA_PORT = 8778; + private boolean myEnabled = false; + private int myPort = DEFAULT_JOLOKIA_PORT; + + /** + * Sets whether the Jolokia adapter is enabled. + * + * @param enabled {@code true} to enable the Jolokia adapter; {@code false} otherwise. + */ + @JsonProperty("enabled") + public void setEnabled(final boolean enabled) + { + myEnabled = enabled; + } + + /** + * Sets the port to be used by the Jolokia adapter. + * + * @param port the port number for the Jolokia adapter. + */ + @JsonProperty("port") + public void setDefaultJolokiaPort(final int port) + { + myPort = port; + } + + /** + * Returns whether the Jolokia adapter is enabled. + * + * @return {@code true} if the Jolokia adapter is enabled; {@code false} otherwise. + */ + @JsonProperty("enabled") + public boolean isEnabled() + { + return myEnabled; + } + + /** + * Returns the port used by the Jolokia adapter. + * + * @return the port number for the Jolokia adapter. + */ + @JsonProperty("port") + public int getPort() + { + return myPort; + } +} diff --git a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/providers/AgentJmxConnectionProvider.java b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/providers/AgentJmxConnectionProvider.java index 3a900046..f9b292d1 100644 --- a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/providers/AgentJmxConnectionProvider.java +++ b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/providers/AgentJmxConnectionProvider.java @@ -15,6 +15,8 @@ package com.ericsson.bss.cassandra.ecchronos.application.providers; import com.datastax.oss.driver.api.core.metadata.Node; +import com.ericsson.bss.cassandra.ecchronos.application.config.Config; +import com.ericsson.bss.cassandra.ecchronos.application.config.connection.JolokiaConfig; import com.ericsson.bss.cassandra.ecchronos.application.config.security.Credentials; import com.ericsson.bss.cassandra.ecchronos.application.config.security.JmxTLSConfig; import com.ericsson.bss.cassandra.ecchronos.application.config.security.Security; @@ -39,7 +41,7 @@ public class AgentJmxConnectionProvider implements DistributedJmxConnectionProvider { private static final Logger LOG = LoggerFactory.getLogger(AgentJmxConnectionProvider.class); - private final DistributedJmxConnectionProviderImpl myDistributedJmxConnectionProviderImpl; + private final DistributedJmxConnectionProvider myDistributedJmxConnectionProviderImpl; /** * Constructs an {@code AgentJmxConnectionProvider} with the specified parameters. @@ -54,21 +56,26 @@ public class AgentJmxConnectionProvider implements DistributedJmxConnectionProvi * if an I/O error occurs during the initialization of the JMX connection provider. */ public AgentJmxConnectionProvider( + final Config config, final Supplier jmxSecurity, final DistributedNativeConnectionProvider distributedNativeConnectionProvider, final EccNodesSync eccNodesSync ) throws IOException { + JolokiaConfig jolokiaConfig = config.getConnectionConfig().getJmxConnection().getJolokiaConfig(); Supplier credentials = () -> convertCredentials(jmxSecurity); Supplier> tls = () -> convertTls(jmxSecurity); LOG.info("Creating DistributedJmxConnectionConfig"); + myDistributedJmxConnectionProviderImpl = DistributedJmxConnectionProviderImpl.builder() .withCqlSession(distributedNativeConnectionProvider.getCqlSession()) .withNodesList(distributedNativeConnectionProvider.getNodes()) .withCredentials(credentials) .withEccNodesSync(eccNodesSync) .withTLS(tls) + .withJolokiaEnabled(jolokiaConfig.isEnabled()) + .withJolokiaPort(jolokiaConfig.getPort()) .build(); } diff --git a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/spring/BeanConfigurator.java b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/spring/BeanConfigurator.java index 83d3ac47..42a0c126 100644 --- a/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/spring/BeanConfigurator.java +++ b/application/src/main/java/com/ericsson/bss/cassandra/ecchronos/application/spring/BeanConfigurator.java @@ -232,12 +232,13 @@ public EccNodesSync eccNodesSync( */ @Bean public DistributedJmxConnectionProvider distributedJmxConnectionProvider( + final Config config, final DistributedNativeConnectionProvider distributedNativeConnectionProvider, final EccNodesSync eccNodesSync ) throws IOException { return getDistributedJmxConnection( - jmxSecurity::get, distributedNativeConnectionProvider, eccNodesSync); + config, jmxSecurity::get, distributedNativeConnectionProvider, eccNodesSync); } @Bean @@ -302,13 +303,14 @@ private DistributedNativeConnectionProvider getDistributedNativeConnection( } private DistributedJmxConnectionProvider getDistributedJmxConnection( + final Config config, final Supplier securitySupplier, final DistributedNativeConnectionProvider distributedNativeConnectionProvider, final EccNodesSync eccNodesSync ) throws IOException { return new AgentJmxConnectionProvider( - securitySupplier, distributedNativeConnectionProvider, eccNodesSync); + config, securitySupplier, distributedNativeConnectionProvider, eccNodesSync); } private void refreshSecurityConfig( diff --git a/application/src/main/resources/ecc.yml b/application/src/main/resources/ecc.yml index 7112da3d..503a4177 100644 --- a/application/src/main/resources/ecc.yml +++ b/application/src/main/resources/ecc.yml @@ -83,7 +83,6 @@ connection: ## ## The class used to provide CQL connections to Apache Cassandra. ## The default provider will be used unless another is specified. - ## The default provider will be used unless another is specified. ## provider: com.ericsson.bss.cassandra.ecchronos.application.providers.AgentNativeConnectionProvider ## @@ -99,6 +98,17 @@ connection: time: 45 unit: MINUTES jmx: + jolokia: + # + # Specifies whether the Jolokia adapter for connecting to JMX objects is enabled or not. + # Default: false (adapter is disabled if not explicitly configured). + # + enabled: false + # + # Defines the port used by Jolokia for accessing JMX objects. + # Default: 8778 (this port will be used if no other port is configured). + # + port: 8778 ## ## The class used to provide JMX connections to Apache Cassandra. ## The default provider will be used unless another is specified. diff --git a/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestConfig.java b/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestConfig.java index 8089448c..e19375d9 100644 --- a/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestConfig.java +++ b/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestConfig.java @@ -317,5 +317,14 @@ public void testInstanceName() { assertThat(nativeConnection.getAgentConnectionConfig().getInstanceName()).isEqualTo("unique_identifier"); } + + @Test + public void testJolokiaConfig() + { + JolokiaConfig jolokiaConfig = config.getConnectionConfig().getJmxConnection().getJolokiaConfig(); + assertThat(jolokiaConfig).isNotNull(); + assertThat(jolokiaConfig.isEnabled()).isTrue(); + assertThat(jolokiaConfig.getPort()).isEqualTo(7887); + } } diff --git a/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestDefaultConfig.java b/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestDefaultConfig.java index cb9bc520..41f9accc 100644 --- a/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestDefaultConfig.java +++ b/application/src/test/java/com/ericsson/bss/cassandra/ecchronos/application/config/TestDefaultConfig.java @@ -16,6 +16,7 @@ import com.ericsson.bss.cassandra.ecchronos.application.config.connection.ConnectionConfig; import com.ericsson.bss.cassandra.ecchronos.application.config.connection.DistributedJmxConnection; +import com.ericsson.bss.cassandra.ecchronos.application.config.connection.JolokiaConfig; import com.ericsson.bss.cassandra.ecchronos.application.config.connection.RetryPolicyConfig; import com.ericsson.bss.cassandra.ecchronos.application.config.repair.FileBasedRepairConfiguration; import com.ericsson.bss.cassandra.ecchronos.application.config.repair.GlobalRepairConfig; @@ -166,4 +167,13 @@ public void testRepairType() RepairType repairType = repairConfig.getRepairType(); assertThat(repairType).isEqualTo(RepairType.VNODE); } + + @Test + public void testJolokiaConfig() + { + JolokiaConfig jolokiaConfig = config.getConnectionConfig().getJmxConnection().getJolokiaConfig(); + assertThat(jolokiaConfig).isNotNull(); + assertThat(jolokiaConfig.isEnabled()).isFalse(); + assertThat(jolokiaConfig.getPort()).isEqualTo(8778); + } } diff --git a/application/src/test/resources/all_set.yml b/application/src/test/resources/all_set.yml index 5d18c36d..7913c822 100644 --- a/application/src/test/resources/all_set.yml +++ b/application/src/test/resources/all_set.yml @@ -47,6 +47,9 @@ connection: time: 45 unit: minutes jmx: + jolokia: + enabled: true + port: 7887 provider: com.ericsson.bss.cassandra.ecchronos.application.providers.AgentJmxConnectionProvider retryPolicy: maxAttempts: 5 diff --git a/connection.impl/pom.xml b/connection.impl/pom.xml index 44cf3df8..157a33f3 100644 --- a/connection.impl/pom.xml +++ b/connection.impl/pom.xml @@ -47,6 +47,11 @@ ${project.version} + + org.jolokia + jolokia-jsr160 + + com.datastax.oss diff --git a/connection.impl/src/main/java/com/ericsson/bss/cassandra/ecchronos/connection/impl/builders/DistributedJmxBuilder.java b/connection.impl/src/main/java/com/ericsson/bss/cassandra/ecchronos/connection/impl/builders/DistributedJmxBuilder.java index ec12b796..4553bd64 100644 --- a/connection.impl/src/main/java/com/ericsson/bss/cassandra/ecchronos/connection/impl/builders/DistributedJmxBuilder.java +++ b/connection.impl/src/main/java/com/ericsson/bss/cassandra/ecchronos/connection/impl/builders/DistributedJmxBuilder.java @@ -20,6 +20,7 @@ import com.datastax.oss.driver.api.core.cql.SimpleStatement; import com.datastax.oss.driver.api.core.metadata.Node; import com.datastax.oss.driver.api.core.servererrors.QueryExecutionException; +import com.ericsson.bss.cassandra.ecchronos.connection.DistributedJmxConnectionProvider; import com.ericsson.bss.cassandra.ecchronos.connection.impl.providers.DistributedJmxConnectionProviderImpl; import com.ericsson.bss.cassandra.ecchronos.data.sync.EccNodesSync; import com.ericsson.bss.cassandra.ecchronos.utils.enums.sync.NodeStatus; @@ -44,6 +45,8 @@ public class DistributedJmxBuilder { private static final Logger LOG = LoggerFactory.getLogger(DistributedJmxBuilder.class); private static final String JMX_FORMAT_URL = "service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi"; + private static final String JMX_JOLOKIA_FORMAT_URL = "service:jmx:jolokia://%s:%d/jolokia"; + private static final int DEFAULT_JOLOKIA_PORT = 8778; private static final int DEFAULT_PORT = 7199; private CqlSession mySession; @@ -51,7 +54,8 @@ public class DistributedJmxBuilder private final ConcurrentHashMap myJMXConnections = new ConcurrentHashMap<>(); private Supplier myCredentialsSupplier; private Supplier> myTLSSupplier; - + private boolean isJolokiaEnabled = false; + private int myJolokiaPort = DEFAULT_JOLOKIA_PORT; private EccNodesSync myEccNodesSync; /** @@ -119,6 +123,18 @@ public final DistributedJmxBuilder withEccNodesSync(final EccNodesSync eccNodesS return this; } + public final DistributedJmxBuilder withJolokiaEnabled(final boolean jolokiaEnabled) + { + isJolokiaEnabled = jolokiaEnabled; + return this; + } + + public final DistributedJmxBuilder withJolokiaPort(final int jolokiaPort) + { + myJolokiaPort = jolokiaPort; + return this; + } + /** * Build the DistributedJmxConnectionProviderImpl instance. * @@ -126,12 +142,10 @@ public final DistributedJmxBuilder withEccNodesSync(final EccNodesSync eccNodesS * @throws IOException * if an I/O error occurs during the creation of connections. */ - public final DistributedJmxConnectionProviderImpl build() throws IOException + public final DistributedJmxConnectionProvider build() throws IOException { createConnections(); return new DistributedJmxConnectionProviderImpl( - myNodesList, - myJMXConnections, this ); } @@ -154,8 +168,8 @@ private void createConnections() throws IOException } /*** - * Creates a JMXconnection to the host. - * @param node + * Creates a JMX connection to the host. + * @param node the node to connect with. * @throws EcChronosException */ public void reconnect(final Node node) throws EcChronosException @@ -163,7 +177,19 @@ public void reconnect(final Node node) throws EcChronosException try { String host = node.getBroadcastRpcAddress().get().getHostString(); - Integer port = getJMXPort(node); + JMXServiceURL jmxUrl; + Integer port; + if (isJolokiaEnabled) + { + port = myJolokiaPort; + jmxUrl = new JMXServiceURL(String.format(JMX_JOLOKIA_FORMAT_URL, host, port)); + } + else + { + port = getJMXPort(node); + jmxUrl = new JMXServiceURL(String.format(JMX_FORMAT_URL, host, port)); + } + if (host.contains(":")) { // Use square brackets to surround IPv6 addresses @@ -171,7 +197,7 @@ public void reconnect(final Node node) throws EcChronosException } LOG.info("Starting to instantiate JMXService with host: {} and port: {}", host, port); - JMXServiceURL jmxUrl = new JMXServiceURL(String.format(JMX_FORMAT_URL, host, port)); + LOG.debug("Connecting JMX through {}, credentials: {}, tls: {}", jmxUrl, isAuthEnabled(), isTLSEnabled()); JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxUrl, createJMXEnv()); if (isConnected(jmxConnector)) @@ -284,4 +310,14 @@ private static boolean isConnected(final JMXConnector jmxConnector) return true; } + + public final List getNodesList() + { + return myNodesList; + } + + public final ConcurrentHashMap getJMXConnections() + { + return myJMXConnections; + } } diff --git a/connection.impl/src/main/java/com/ericsson/bss/cassandra/ecchronos/connection/impl/providers/DistributedJmxConnectionProviderImpl.java b/connection.impl/src/main/java/com/ericsson/bss/cassandra/ecchronos/connection/impl/providers/DistributedJmxConnectionProviderImpl.java index ea08bf2f..1390dafd 100644 --- a/connection.impl/src/main/java/com/ericsson/bss/cassandra/ecchronos/connection/impl/providers/DistributedJmxConnectionProviderImpl.java +++ b/connection.impl/src/main/java/com/ericsson/bss/cassandra/ecchronos/connection/impl/providers/DistributedJmxConnectionProviderImpl.java @@ -39,19 +39,14 @@ public class DistributedJmxConnectionProviderImpl implements DistributedJmxConne /** * Constructs a DistributedJmxConnectionProviderImpl with the specified list of nodes and JMX connections. * - * @param nodesList - * the list of Node objects representing the nodes to manage JMX connections for. - * @param jmxConnections - * a ConcurrentHashMap mapping each node's UUID to its corresponding JMXConnector. + * @param distributedJmxBuilder DistributedJmxBuilder. */ public DistributedJmxConnectionProviderImpl( - final List nodesList, - final ConcurrentHashMap jmxConnections, final DistributedJmxBuilder distributedJmxBuilder ) { - myNodesList = nodesList; - myJMXConnections = jmxConnections; + myNodesList = distributedJmxBuilder.getNodesList(); + myJMXConnections = distributedJmxBuilder.getJMXConnections(); myDistributedJmxBuilder = distributedJmxBuilder; } @@ -170,5 +165,4 @@ public void add(final Node node) throws IOException } } - } diff --git a/pom.xml b/pom.xml index 4158a229..e5897684 100644 --- a/pom.xml +++ b/pom.xml @@ -159,6 +159,7 @@ 3.0.1 1.6 + 1.7.1 false ${skipTests} @@ -347,6 +348,12 @@ ${org.yaml.snakeyaml.version} + + org.jolokia + jolokia-jsr160 + ${jolokia.adapter.version} + + org.mockito