modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
| 13 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageClusterCredentialsJob.java
| 45 ++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java
| 108 ++++++----
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java
| 17 +
modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/StorageSession.java
| 18 +
5 files changed, 167 insertions(+), 34 deletions(-)
New commits:
commit 54df17b99aa8ef362a95842ee02b9fd72cfcaef7
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Oct 22 16:30:11 2013 -0500
Add code to update Cassandra password via a direct CQL query using the existing open
session.
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java
index 2a47670..b14db38 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java
@@ -10,6 +10,7 @@ import org.rhq.core.domain.common.composite.SystemSetting;
import org.rhq.core.domain.common.composite.SystemSettings;
import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.system.SystemManagerLocal;
+import org.rhq.server.metrics.StorageSession;
/**
* @author John Sanda
@@ -17,9 +18,14 @@ import org.rhq.enterprise.server.system.SystemManagerLocal;
@Stateless
public class StorageClusterSettingsManagerBean implements
StorageClusterSettingsManagerLocal {
+ private static final String UPDATE_PASSWORD_QUERY = "ALTER USER '%s'
WITH PASSWORD '%s'";
+
@EJB
private SystemManagerLocal systemManager;
+ @EJB
+ private StorageClientManagerBean storageClienManager;
+
@Override
@RequiredPermission(Permission.MANAGE_SETTINGS)
public StorageClusterSettings getClusterSettings(Subject subject) {
@@ -76,9 +82,20 @@ public class StorageClusterSettingsManagerBean implements
StorageClusterSettings
settings.put(SystemSetting.STORAGE_USERNAME, clusterSettings.getUsername());
}
if (clusterSettings.getPasswordHash() != null) {
+ this.updateStorageClusterCredentials(clusterSettings);
settings.put(SystemSetting.STORAGE_PASSWORD,
clusterSettings.getPasswordHash());
}
systemManager.setStorageClusterSettings(subject, settings);
}
+ private void updateStorageClusterCredentials(StorageClusterSettings
newClusterSettings) {
+ SystemSettings currentSettings = systemManager.getUnmaskedSystemSettings(true);
+ String currentPassword = currentSettings.get(SystemSetting.STORAGE_PASSWORD);
+
+ if (!currentPassword.equals(newClusterSettings.getPasswordHash())) {
+ StorageSession session = this.storageClienManager.getSession();
+ session.execute(String.format(UPDATE_PASSWORD_QUERY,
currentSettings.get(SystemSetting.STORAGE_USERNAME),
+ newClusterSettings.getPasswordHash()));
+ }
+ }
}
commit 705c15d24c86a52f3c655e3959cc9768d0461888
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Tue Oct 22 10:42:50 2013 -0500
Add code to update the storage session when credentials get update in the system
settings table. Created a quartz job to trigger the refresh every 2 minutes.
The process to refresh the session is as follows:
1) Get new credentials from the database
2) Create a new session with new credentials
3) Replace existing session with newly created one
4) Allow few minutes for existing session drainage
5) Shutdown old session
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index d5878c6..2538bd7 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -87,6 +87,7 @@ import
org.rhq.enterprise.server.scheduler.jobs.DynaGroupAutoRecalculationJob;
import org.rhq.enterprise.server.scheduler.jobs.PurgePluginsJob;
import org.rhq.enterprise.server.scheduler.jobs.PurgeResourceTypesJob;
import org.rhq.enterprise.server.scheduler.jobs.SavedSearchResultCountRecalculationJob;
+import org.rhq.enterprise.server.scheduler.jobs.StorageClusterCredentialsJob;
import org.rhq.enterprise.server.scheduler.jobs.StorageClusterInitJob;
import org.rhq.enterprise.server.scheduler.jobs.StorageClusterReadRepairJob;
import org.rhq.enterprise.server.storage.StorageClientManagerBean;
@@ -740,6 +741,16 @@ public class StartupBean implements StartupLocal {
}
try {
+ // Storage cluster credentials refresh job
+ final long initialDelay = 1000L * 60 * 5;
+ final long interval = 1000L * 60 * 2;
+ schedulerBean.scheduleSimpleRepeatingJob(StorageClusterCredentialsJob.class,
true, false, initialDelay,
+ interval);
+ } catch (Exception e) {
+ log.error("Cannot schedule storage cluster credentials refresh
job.", e);
+ }
+
+ try {
String cronString = "0 30 0 ? * SUN *"; // every sunday starting
at 00:30.
schedulerBean.scheduleSimpleCronJob(StorageClusterReadRepairJob.class, true,
true, cronString);
} catch (Exception e) {
@@ -925,4 +936,4 @@ public class StartupBean implements StartupLocal {
+ ") Server started.");
log.info("--------------------------------------------------"); // 50
dashes
}
-}
+}
\ No newline at end of file
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageClusterCredentialsJob.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageClusterCredentialsJob.java
new file mode 100644
index 0000000..f8eea6a
--- /dev/null
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/StorageClusterCredentialsJob.java
@@ -0,0 +1,45 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.server.scheduler.jobs;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Stefan Negrea
+ */
+public class StorageClusterCredentialsJob extends AbstractStatefulJob {
+
+ private Log log = LogFactory.getLog(StorageClusterCredentialsJob.class);
+
+ @Override
+ public void executeJobCode(JobExecutionContext context) throws JobExecutionException
{
+ log.info("Preparing to run init job on storage cluster");
+ boolean success =
LookupUtil.getStorageClientManager().refreshCredentialsAndSession();
+ if (!success) {
+ log.error("Storage session credentials not succesfully
refreshed");
+ } else {
+ log.debug("Storage session credentials succesfully refreshed");
+ }
+ }
+}
diff --git
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java
index 98d1405..cab45e5 100644
---
a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java
+++
b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java
@@ -88,6 +88,10 @@ public class StorageClientManagerBean {
private boolean initialized;
private StorageClusterMonitor storageClusterMonitor;
+ private String cachedStorageUsername;
+ private String cachedStoragePassword;
+
+
/**
* @return true if the storage subsystem is running
*/
@@ -101,37 +105,9 @@ public class StorageClientManagerBean {
log.info("Initializing storage client subsystem");
- // Always get the creds from the DB, system props may not be up to date at
install time
- // the code assumes the passwords to be obfuscated, because they can also come
that way from other sources
- // (like property files). So let's make our lives easy and always use
obfuscated passwords.
- SystemSettings settings = systemManager.getObfuscatedSystemSettings(true);
- final String username = settings.get(SystemSetting.STORAGE_USERNAME);
- final String password = settings.get(SystemSetting.STORAGE_PASSWORD);
-
- List<StorageNode> storageNodes = new ArrayList<StorageNode>();
- for (StorageNode storageNode : storageNodeManager.getStorageNodes()) {
- // We only want clustered nodes here because we won't be able to connect
to
- // node that is not part of the cluster. The filtering here on the operation
- // mode is somewhat convservative because we could also include
ADD_MAINTENANCE
- // and REMOVE_MAINTENANCE, but this errors on the side of being safe.
Lastly,
- // if a storage node does not have a resource, then that means it was was
- // deployed prior to installing the server.
- if (storageNode.getOperationMode() == StorageNode.OperationMode.NORMAL
- || storageNode.getOperationMode() ==
StorageNode.OperationMode.MAINTENANCE
- || storageNode.getResource() == null) {
- storageNodes.add(storageNode);
- }
- }
-
- if (storageNodes.isEmpty()) {
- throw new IllegalStateException(
- "There is no storage node metadata stored in the relational
database. This may have happened as a "
- + "result of running dbsetup or deleting rows from
rhq_storage_node table. Please re-install the "
- + "storage node to fix this issue.");
- }
-
+ Session wrappedSession;
try {
- checkSchemaCompability(username, password, storageNodes);
+ wrappedSession = createSession();
} catch (NoHostAvailableException e) {
initialized = false;
log.warn("Storage client subsystem wasn't initialized because it
wasn't possible to connect to the"
@@ -139,7 +115,8 @@ public class StorageClientManagerBean {
+ " as soon as possible.");
return initialized;
}
- Session wrappedSession = createSession(username, password, storageNodes);
+
+ wrappedSession = createSession();
session = new StorageSession(wrappedSession);
storageClusterMonitor = new StorageClusterMonitor();
@@ -155,6 +132,40 @@ public class StorageClientManagerBean {
return initialized;
}
+ public synchronized boolean refreshCredentialsAndSession() {
+ if (!initialized) {
+ if (log.isDebugEnabled()) {
+ log.debug("Storage client subsystem not initialized. Skipping
session refresh.");
+ }
+ return false;
+ }
+
+ SystemSettings settings = systemManager.getObfuscatedSystemSettings(true);
+ String username = settings.get(SystemSetting.STORAGE_USERNAME);
+ String password = settings.get(SystemSetting.STORAGE_PASSWORD);
+
+ if ((username != null && !username.equals(this.cachedStorageUsername))
+ || (password != null &&
!password.equals(this.cachedStoragePassword))) {
+
+ Session wrappedSession;
+ try {
+ wrappedSession = createSession();
+ } catch (NoHostAvailableException e) {
+ initialized = false;
+ log.warn("Storage client subsystem wasn't initialized because it
wasn't possible to connect to the"
+ + " storage cluster. The RHQ server is set to MAINTENANCE mode.
Please start the storage cluster"
+ + " as soon as possible.");
+ return initialized;
+ }
+
+ session.registerNewSession(wrappedSession);
+ initialized = true;
+ return true;
+ }
+
+ return true;
+ }
+
/**
* Checks storage node schema compatibility.
*
@@ -227,7 +238,38 @@ public class StorageClientManagerBean {
return storageClusterMonitor != null &&
storageClusterMonitor.isClusterAvailable();
}
- private Session createSession(String username, String password,
List<StorageNode> storageNodes) {
+ private Session createSession() {
+ // Always get the creds from the DB, system props may not be up to date at
install time
+ // the code assumes the passwords to be obfuscated, because they can also come
that way from other sources
+ // (like property files). So let's make our lives easy and always use
obfuscated passwords.
+ SystemSettings settings = systemManager.getObfuscatedSystemSettings(true);
+ this.cachedStorageUsername = settings.get(SystemSetting.STORAGE_USERNAME);
+ this.cachedStoragePassword = settings.get(SystemSetting.STORAGE_PASSWORD);
+
+ List<StorageNode> storageNodes = new ArrayList<StorageNode>();
+ for (StorageNode storageNode : storageNodeManager.getStorageNodes()) {
+ // We only want clustered nodes here because we won't be able to connect
to
+ // node that is not part of the cluster. The filtering here on the operation
+ // mode is somewhat convservative because we could also include
ADD_MAINTENANCE
+ // and REMOVE_MAINTENANCE, but this errors on the side of being safe.
Lastly,
+ // if a storage node does not have a resource, then that means it was was
+ // deployed prior to installing the server.
+ if (storageNode.getOperationMode() == StorageNode.OperationMode.NORMAL
+ || storageNode.getOperationMode() ==
StorageNode.OperationMode.MAINTENANCE
+ || storageNode.getResource() == null) {
+ storageNodes.add(storageNode);
+ }
+ }
+
+ if (storageNodes.isEmpty()) {
+ throw new IllegalStateException(
+ "There is no storage node metadata stored in the relational
database. This may have happened as a "
+ + "result of running dbsetup or deleting rows from
rhq_storage_node table. Please re-install the "
+ + "storage node to fix this issue.");
+ }
+
+ checkSchemaCompability(this.cachedStorageUsername, this.cachedStoragePassword,
storageNodes);
+
if (log.isDebugEnabled()) {
log.debug("Initializing session to connect to storage node
cluster");
}
@@ -250,7 +292,7 @@ public class StorageClientManagerBean {
}
cluster = new ClusterBuilder().addContactPoints(hostNames.toArray(new
String[hostNames.size()]))
- .withCredentialsObfuscated(username, password).withPort(port)
+ .withCredentialsObfuscated(this.cachedStorageUsername,
this.cachedStoragePassword).withPort(port)
.withLoadBalancingPolicy(new RoundRobinPolicy())
.withRetryPolicy(new
LoggingRetryPolicy(DefaultRetryPolicy.INSTANCE)).withCompression(compression).build();
diff --git
a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/StorageSession.java
b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/StorageSession.java
index 60f3fbd..34eada1 100644
---
a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/StorageSession.java
+++
b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/StorageSession.java
@@ -34,6 +34,24 @@ public class StorageSession implements Host.StateListener {
this.wrappedSession.getCluster().register(this);
}
+ public void registerNewSession(Session newWrappedSession) {
+ Session oldWrappedSession = this.wrappedSession;
+
+
+ this.wrappedSession = newWrappedSession;
+ this.wrappedSession.getCluster().register(this);
+
+ oldWrappedSession.getCluster().unregister(this);
+
+ // initial waiting before the first check
+ try {
+ Thread.sleep(60000L);
+ } catch (InterruptedException e) {
+ // nothing
+ }
+ oldWrappedSession.shutdown();
+ }
+
public void addStorageStateListener(StorageStateListener listener) {
listeners.add(listener);
}