/*******************************************************************************
* Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com>
* This file is part of Gluster Management Gateway.
*
* Gluster Management Gateway 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; either
* version 3 of the License, or (at your option) any later version.
*
* Gluster Management Gateway 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, see
* <http://www.gnu.org/licenses/>.
*******************************************************************************/
package org.gluster.storage.management.gateway.services;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityTransaction;
import org.apache.log4j.Logger;
import org.gluster.storage.management.core.constants.CoreConstants;
import org.gluster.storage.management.core.exceptions.ConnectionException;
import org.gluster.storage.management.core.exceptions.GlusterRuntimeException;
import org.gluster.storage.management.core.model.GlusterServer;
import org.gluster.storage.management.core.utils.LRUCache;
import org.gluster.storage.management.gateway.data.ClusterInfo;
import org.gluster.storage.management.gateway.data.PersistenceDao;
import org.gluster.storage.management.gateway.data.ServerInfo;
import org.gluster.storage.management.gateway.utils.ServerUtil;
import org.gluster.storage.management.gateway.utils.SshUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Service class for functionality related to clusters
*/
@Component
public class ClusterService {
@Autowired
private PersistenceDao<ClusterInfo> clusterDao;
@Autowired
private PersistenceDao<ServerInfo> serverDao;
@Autowired
private GlusterServerService glusterServerService;
@Autowired
private SshUtil sshUtil;
@Autowired
private ServerUtil serverUtil;
private LRUCache<String, GlusterServer> onlineServerCache = new LRUCache<String, GlusterServer>(3);
private static final Logger logger = Logger.getLogger(ClusterService.class);
public void addOnlineServer(String clusterName, GlusterServer server) {
onlineServerCache.put(clusterName, server);
}
public void removeOnlineServer(String clusterName) {
onlineServerCache.remove(clusterName);
}
// uses cache
public GlusterServer getOnlineServer(String clusterName, String exceptServerName) {
GlusterServer server = onlineServerCache.get(clusterName);
if (server != null && !server.getName().equalsIgnoreCase(exceptServerName)) {
return server;
}
return getNewOnlineServer(clusterName, exceptServerName);
}
public GlusterServer getNewOnlineServer(String clusterName) {
return getNewOnlineServer(clusterName, "");
}
public GlusterServer getOnlineServer(String clusterName) {
return getOnlineServer(clusterName, "");
}
// Doesn't use cache
public GlusterServer getNewOnlineServer(String clusterName, String exceptServerName) {
ClusterInfo cluster = getCluster(clusterName);
if (cluster == null) {
throw new GlusterRuntimeException("Cluster [" + clusterName + "] is not found!");
}
for (ServerInfo serverInfo : cluster.getServers()) {
GlusterServer server = new GlusterServer(serverInfo.getName());
try {
serverUtil.fetchServerDetails(server); // Online status come with server details
// server is online. add it to cache and return
if (server.isOnline() && !server.getName().equalsIgnoreCase(exceptServerName)) {
addOnlineServer(clusterName, server);
return server;
}
} catch (ConnectionException e) {
// server is offline. continue checking next one.
continue;
}
}
// no online server found.
throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]");
}
public List<ClusterInfo> getAllClusters() {
return clusterDao.findAll();
}
public ClusterInfo getCluster(String clusterName) {
List<ClusterInfo> clusters = clusterDao.findBy("UPPER(name) = ?1", clusterName.toUpperCase());
if(clusters.size() == 0) {
return null;
}
return clusters.get(0);
}
public ClusterInfo getClusterForServer(String serverName) {
List<ServerInfo> servers = serverDao.findBy("UPPER(name) = ?1", serverName.toUpperCase());
if(servers.size() == 0) {
return null;
}
return servers.get(0).getCluster();
}
public void createCluster(String clusterName) {
EntityTransaction txn = clusterDao.startTransaction();
ClusterInfo cluster = new ClusterInfo();
cluster.setName(clusterName);
try {
clusterDao.save(cluster);
txn.commit();
} catch (RuntimeException e) {
txn.rollback();
logger.error("Exception while trying to save cluster [" + clusterName + "] : [" + e.getMessage() + "]", e);
throw e;
}
}
public void registerCluster(String clusterName, String knownServer) {
EntityTransaction txn = clusterDao.startTransaction();
ClusterInfo cluster = new ClusterInfo();
cluster.setName(clusterName);
GlusterServer server = new GlusterServer(knownServer);
try {
List<GlusterServer> glusterServers = glusterServerService.getGlusterServers(server.getName());
List<ServerInfo> servers = new ArrayList<ServerInfo>();
for(GlusterServer glusterServer : glusterServers) {
String serverName = glusterServer.getName();
serverUtil.fetchServerDetails(glusterServer);
if(glusterServer.isOnline()) {
checkAndSetupPublicKey(serverName);
}
ServerInfo serverInfo = new ServerInfo(serverName);
serverInfo.setCluster(cluster);
clusterDao.save(serverInfo);
servers.add(serverInfo);
}
cluster.setServers(servers);
clusterDao.save(cluster);
txn.commit();
} catch(RuntimeException e) {
logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e);
txn.rollback();
logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e);
throw e;
}
}
private void checkAndSetupPublicKey(String serverName) {
if(sshUtil.isPublicKeyInstalled(serverName)) {
return;
}
if(!sshUtil.hasDefaultPassword(serverName)) {
// public key not installed, default password doesn't work. can't install public key
throw new GlusterRuntimeException(
"Gluster Management Gateway uses the default password to set up keys on the server."
+ CoreConstants.NEWLINE + "However it seems that the password on server [" + serverName
+ "] has been changed manually." + CoreConstants.NEWLINE
+ "Please reset it back to the standard default password and try again.");
}
// install public key (this will also disable password based ssh login)
sshUtil.installPublicKey(serverName);
}
public void unregisterCluster(String clusterName) {
ClusterInfo cluster = getCluster(clusterName);
if (cluster == null) {
throw new GlusterRuntimeException("Cluster [" + clusterName + "] doesn't exist!");
}
unregisterCluster(cluster);
}
public void unregisterCluster(ClusterInfo cluster) {
EntityTransaction txn = clusterDao.startTransaction();
try {
for(ServerInfo server : cluster.getServers()) {
clusterDao.delete(server);
}
cluster.getServers().clear();
clusterDao.update(cluster);
clusterDao.delete(cluster);
txn.commit();
} catch (RuntimeException e) {
logger.error("Error in unregistering cluster [" + cluster.getName() + "] : " + e.getMessage(), e);
txn.rollback();
throw e;
}
}
public void mapServerToCluster(String clusterName, String serverName) {
EntityTransaction txn = clusterDao.startTransaction();
ClusterInfo cluster = getCluster(clusterName);
ServerInfo server = new ServerInfo(serverName);
server.setCluster(cluster);
try {
clusterDao.save(server);
cluster.addServer(server);
clusterDao.update(cluster);
txn.commit();
} catch (Exception e) {
txn.rollback();
throw new GlusterRuntimeException("Couldn't create cluster-server mapping [" + clusterName + "]["
+ serverName + "]! Error: " + e.getMessage(), e);
}
}
public void unmapServerFromCluster(String clusterName, String serverName) {
EntityTransaction txn = clusterDao.startTransaction();
ClusterInfo cluster = getCluster(clusterName);
List<ServerInfo> servers = cluster.getServers();
for(ServerInfo server : servers) {
if(server.getName().equalsIgnoreCase(serverName)) {
servers.remove(server);
clusterDao.delete(server);
break;
}
}
try {
clusterDao.update(cluster);
txn.commit();
} catch(Exception e) {
txn.rollback();
throw new GlusterRuntimeException("Couldn't unmap server [" + serverName + "] from cluster [" + clusterName
+ "]! Error: " + e.getMessage(), e);
}
}
}