/* * * * RHQ Management Platform * * Copyright (C) 2005-2012 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, version 2, as * * published by the Free Software Foundation, and/or the GNU Lesser * * General Public License, version 2.1, also as published by the Free * * Software Foundation. * * * * 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 and the GNU Lesser General Public License * * for more details. * * * * You should have received a copy of the GNU General Public License * * and the GNU Lesser General Public License along with this program; * * if not, write to the Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ package org.rhq.cassandra.schema; import java.util.Properties; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.exceptions.AuthenticationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rhq.core.util.obfuscation.PicketBoxObfuscator; /** * @author Stefan Negrea */ abstract class AbstractManager { private static final String MANAGEMENT_BASE_FOLDER = "management"; protected static final String DEFAULT_CASSANDRA_USER = "cassandra"; protected static final String DEFAULT_CASSANDRA_PASSWORD = "-1e4662ac0d7ddef155fd5fac8f894a49"; private final Log log = LogFactory.getLog(AbstractManager.class); protected UpdateFolderFactory updateFolderFactory; enum Query { USER_EXISTS, SCHEMA_EXISTS, VERSION_COLUMNFAMILY_EXISTS, VERSION, REPLICATION_FACTOR, INSERT_SCHEMA_VERSION; @Override public String toString() { return this.name().toLowerCase(); } } private SessionManager sessionManager; private final String username; private final String password; private final int cqlPort; private final String[] nodes; private final UpdateFile managementTasks; protected AbstractManager(String username, String password, String[] nodes, int cqlPort, SessionManager sessionManager, UpdateFolderFactory updateFolderFactory) { this.username = username; this.password = password; this.cqlPort = cqlPort; this.nodes = nodes; this.sessionManager = sessionManager; try { UpdateFolder managementFolder = updateFolderFactory.newUpdateFolder(MANAGEMENT_BASE_FOLDER); managementTasks = managementFolder.getUpdateFiles().get(0); } catch (Exception e) { throw new RuntimeException("Unable create storage node session.", e); } this.updateFolderFactory = updateFolderFactory; } /** * Init the storage cluster session with the username and password provided * at creation. */ protected void initClusterSession() { initClusterSession(username, password); } /** * Init the storage cluster session with provided username and password. * * @param username * @param password */ protected void initClusterSession(String username, String password) { sessionManager.initSession(username, password, cqlPort, nodes); } /** * Shutdown the storage cluster connection. */ protected void shutdownClusterConnection() { log.info("Shutting down existing cluster connections"); sessionManager.shutdownCluster(); } /** * @return The actual size of the cluster which includes both specified and discovered nodes */ protected int getActualClusterSize() { return sessionManager.getSession().getCluster().getMetadata().getAllHosts().size(); } /** * @return the username */ protected String getUsername() { return username; } /** * @return the password */ protected String getPassword() { return password; } /** * @return the cqlPort */ protected int getCqlPort() { return cqlPort; } /** * Runs a CQL query to check the existence of the RHQ user on the storage cluster. * * @return true if the RHQ user exists, false otherwise */ protected boolean userExists() { try { ResultSet resultSet = execute("SELECT * FROM system_auth.users WHERE name = '" + username + "'"); return !resultSet.all().isEmpty(); } catch (Exception e) { log.error(e); throw new RuntimeException(e); } } /** * Run a CQL query to check the existence of the RHQ schema. * * @return true if the RHQ schema exists, false otherwise */ protected boolean schemaExists() { try { ResultSet resultSet = execute("SELECT * FROM system.schema_keyspaces WHERE keyspace_name = 'rhq'"); if (!resultSet.all().isEmpty()) { resultSet = execute( "SELECT * FROM system.schema_columnfamilies " + "WHERE keyspace_name='rhq' AND columnfamily_name='schema_version'"); return !resultSet.all().isEmpty(); } return false; } catch (AuthenticationException exp) { throw exp; } catch (Exception e) { log.error(e); throw new RuntimeException(e); } } /** * Run a CQL query to retrieve the installed storage schema version. * * @return current RHQ schema version */ protected int getInstalledSchemaVersion() { int maxVersion = 0; try { ResultSet resultSet = execute("SELECT version FROM rhq.schema_version"); for (Row row : resultSet.all()) { if (maxVersion < row.getInt(0)) { maxVersion = row.getInt(0); } } } catch (Exception e) { log.error(e); throw new RuntimeException(e); } return maxVersion; } /** * Calculate the replication factor based on the input cluster size. * * @return calculated replication factor */ protected int calculateNewReplicationFactor() { int replicationFactor; int actualClusterSize = getActualClusterSize(); if (actualClusterSize < 3) { replicationFactor = actualClusterSize; } else if (actualClusterSize < 4) { replicationFactor = 2; } else { replicationFactor = 3; } return replicationFactor; } /** * Run a CQL query to retrieve the current replication factor for RHQ schema. * * @return existing replication factor */ protected int queryReplicationFactor() { int replicationFactor = 1; try { ResultSet resultSet = execute( "SELECT strategy_options FROM system.schema_keyspaces where keyspace_name='rhq'"); Row row = resultSet.one(); String replicationFactorString = "replication_factor\""; String resultString = row.getString(0); resultString = resultString.substring(resultString.indexOf(replicationFactorString) + replicationFactorString.length()); resultString = resultString.substring(resultString.indexOf('"') + 1); resultString = resultString.substring(0, resultString.indexOf('"')); replicationFactor = Integer.parseInt(resultString); } catch (Exception e) { log.error(e); } return replicationFactor; } /** * Execute all the queries in an update file as returned by @link {@link UpdateFile#getOrderedSteps()}. * * @param updateFile update file * @return list of result sets, one for each executed query. */ protected void execute(UpdateFile updateFile) { execute(updateFile, null); } /** * Execute all the queries in an update file as returned by @link {@link UpdateFile#getOrderedSteps(Properties))} with * the given property (name,value). * * @param updateFile update file * @param propertyName property name * @param propertyValue property value * @return list of result sets, one for each executed query. */ protected void execute(UpdateFile updateFile, String propertyName, String propertyValue) { Properties properties = new Properties(); properties.put(propertyName, propertyValue); execute(updateFile, properties); } /** * Execute all the queries in an update file as returned by @link {@link UpdateFile#getOrderedSteps(Properties))} with * the given property (name,value). * * @param updateFile update file * @param properties properties * @return list of result sets, one for each executed query. */ protected void execute(UpdateFile updateFile, Properties properties) { log.info("Applying update file: " + updateFile); for (Step step : updateFile.getOrderedSteps()) { log.debug(step); step.bind(properties); step.setSession(sessionManager.getSession()); step.execute(); } log.info("Applied update file: " + updateFile); } /** * Execute a CQL query. * * @param query query * @return result for the query */ protected ResultSet execute(String query) { return sessionManager.getSession().execute(query); } }