summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShireesh Anjal <shireesh@gluster.com>2011-06-01 21:01:28 +0530
committerShireesh Anjal <shireesh@gluster.com>2011-06-02 16:43:16 +0530
commit21681dbcefdaa854ca1f8ac210914438ca903443 (patch)
tree9a39283d6a4b9c9bceeab7ab0c3755851b7b68df /src
parent4507d18b193524c69186f1cfb26e99daa8d50fdc (diff)
Design changes - introducing cluster-server mapping on gateway
Diffstat (limited to 'src')
-rw-r--r--src/com.gluster.storage.management.server/.project1
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java93
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java84
3 files changed, 136 insertions, 42 deletions
diff --git a/src/com.gluster.storage.management.server/.project b/src/com.gluster.storage.management.server/.project
index 86d34a3b..259b3726 100644
--- a/src/com.gluster.storage.management.server/.project
+++ b/src/com.gluster.storage.management.server/.project
@@ -37,6 +37,5 @@
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
- <nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java
index b364db29..15992608 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java
@@ -41,6 +41,7 @@ import org.springframework.stereotype.Component;
import com.gluster.storage.management.core.constants.CoreConstants;
import com.gluster.storage.management.core.exceptions.ConnectionException;
+import com.gluster.storage.management.core.exceptions.GlusterRuntimeException;
import com.gluster.storage.management.core.model.GlusterServer;
import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS;
import com.gluster.storage.management.core.model.Status;
@@ -65,6 +66,9 @@ public class GlusterServersResource extends AbstractServersResource {
@Autowired
private PersistenceDao<ClusterInfo> clusterDao;
+ @Autowired
+ private SshUtil sshUtil;
+
protected void fetchServerDetails(GlusterServer server) {
try {
server.setStatus(SERVER_STATUS.ONLINE);
@@ -170,6 +174,28 @@ public class GlusterServersResource extends AbstractServersResource {
return new GlusterServerResponse(status, server);
}
+ private Status performAddServer(String clusterName, String serverName) {
+ GlusterServer onlineServer = getOnlineServer(clusterName);
+ if(onlineServer == null) {
+ return new Status(Status.STATUS_CODE_FAILURE,
+ "No online server found in cluster [" + clusterName + "]");
+ }
+
+ Status status;
+ try {
+ status = glusterUtil.addServer(serverName, onlineServer.getName());
+ } catch(ConnectionException e) {
+ onlineServer = getNewOnlineServer(clusterName);
+ if(onlineServer == null) {
+ return new Status(Status.STATUS_CODE_FAILURE,
+ "No online server found in cluster [" + clusterName + "]");
+ }
+ status = glusterUtil.addServer(serverName, onlineServer.getName());
+ }
+
+ return status;
+ }
+
@POST
@Produces(MediaType.TEXT_XML)
public GlusterServerResponse addServer(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
@@ -180,33 +206,51 @@ public class GlusterServersResource extends AbstractServersResource {
+ "] doesn't exist!"), null);
}
+ boolean publicKeyInstalled = sshUtil.isPublicKeyInstalled(serverName);
+ if(!publicKeyInstalled && !sshUtil.hasDefaultPassword(serverName)) {
+ // public key not installed, default password doesn't work. return with error.
+ return new GlusterServerResponse(new Status(Status.STATUS_CODE_FAILURE,
+ "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."), null);
+ }
+
if(!cluster.getServers().isEmpty()) {
- GlusterServer onlineServer = getOnlineServer(clusterName);
- if(onlineServer == null) {
- return new GlusterServerResponse(new Status(Status.STATUS_CODE_FAILURE,
- "No online server found in cluster [" + clusterName + "]"), null);
- }
-
- Status status;
- try {
- status = glusterUtil.addServer(serverName, onlineServer.getName());
- } catch(ConnectionException e) {
- onlineServer = getNewOnlineServer(clusterName);
- if(onlineServer == null) {
- return new GlusterServerResponse(new Status(Status.STATUS_CODE_FAILURE,
- "No online server found in cluster [" + clusterName + "]"), null);
- }
- status = glusterUtil.addServer(serverName, onlineServer.getName());
- }
-
- if (!status.isSuccess()) {
+ Status status = performAddServer(clusterName, serverName);
+ if(!status.isSuccess()) {
return new GlusterServerResponse(status, null);
}
} else {
- // this is the first server to be added to the cluster, which means
- // no gluster operation required. just add it to the cluster-server mapping
+ // this is the first server to be added to the cluster, which means no
+ // gluster CLI operation required. just add it to the cluster-server mapping
}
+ // fetch server details
+ GlusterServerResponse serverResponse = getGlusterServer(clusterName, serverName);
+
+ try {
+ // install public key (this will also disable password based ssh login)
+ sshUtil.installPublicKey(serverName);
+ } catch(Exception e) {
+ return new GlusterServerResponse(new Status(Status.STATUS_CODE_PART_SUCCESS,
+ "Public key could not be installed! Error: [" + e.getMessage()
+ + "]"), serverResponse.getGlusterServer());
+ }
+
+ try {
+ addServerToCluster(clusterName, serverName);
+ } catch (Exception e){
+ return new GlusterServerResponse(new Status(Status.STATUS_CODE_PART_SUCCESS,
+ "Exception while trying to save cluster-server mapping [" + clusterName + "][" + serverName
+ + "]: [" + e.getMessage() + "]"), serverResponse.getGlusterServer());
+ }
+
+ return serverResponse;
+ }
+
+ private void addServerToCluster(String clusterName, String serverName) {
+ ClusterInfo cluster;
EntityTransaction txn = clusterDao.startTransaction();
// Inside a transaction, we must fetch the ClusterInfo object again.
cluster = getCluster(clusterName);
@@ -215,13 +259,8 @@ public class GlusterServersResource extends AbstractServersResource {
txn.commit();
} catch (Exception e) {
txn.rollback();
- return new GlusterServerResponse(new Status(Status.STATUS_CODE_FAILURE,
- "Exception while trying to save cluster-server mapping [" + clusterName + "][" + serverName
- + "]: [" + e.getMessage() + "]"), null);
+ throw new GlusterRuntimeException("Couldn't commit transaction! Error: " + e.getMessage(), e);
}
-
- // TODO: Install ssh key on new server
- return getGlusterServer(clusterName, serverName);
}
private ClusterInfo getCluster(String clusterName) {
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java
index cac71f9c..04639ba9 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java
@@ -20,6 +20,8 @@ package com.gluster.storage.management.server.utils;
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
@@ -30,12 +32,14 @@ import org.springframework.stereotype.Component;
import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
+import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import com.gluster.storage.management.core.constants.CoreConstants;
import com.gluster.storage.management.core.exceptions.ConnectionException;
import com.gluster.storage.management.core.exceptions.GlusterRuntimeException;
+import com.gluster.storage.management.core.utils.FileUtil;
import com.gluster.storage.management.core.utils.LRUCache;
import com.gluster.storage.management.core.utils.ProcessResult;
@@ -44,13 +48,78 @@ import com.gluster.storage.management.core.utils.ProcessResult;
*/
@Component
public class SshUtil {
+ private static final String TEMP_DIR = "/tmp/";
+ private static final String SSH_AUTHORIZED_KEYS_DIR = "/root/.ssh/";
+ private static final String SSH_AUTHORIZED_KEYS_FILE = "authorized_keys";
+ private static final String SSH_AUTHORIZED_KEYS_PATH = SSH_AUTHORIZED_KEYS_DIR + SSH_AUTHORIZED_KEYS_FILE;
private LRUCache<String, Connection> sshConnCache = new LRUCache<String, Connection>(10);
- private static final File PEM_FILE = new File(CoreConstants.USER_HOME + "/" + ".ssh/id_rsa");
+ private static final File PEM_FILE = new File(CoreConstants.USER_HOME + File.separator + ".ssh/id_rsa");
+ private static final File PUBLIC_KEY_FILE = new File(CoreConstants.USER_HOME + File.separator + ".ssh/id_rsa.pub");
+
// TODO: Make user name configurable
private static final String USER_NAME = "root";
// TODO: Make default password configurable
private static final String DEFAULT_PASSWORD = "syst3m";
+ public boolean hasDefaultPassword(String serverName) {
+ try {
+ getConnectionWithPassword(serverName);
+ return true;
+ } catch(ConnectionException e) {
+ return false;
+ }
+ }
+
+ public boolean isPublicKeyInstalled(String serverName) {
+ try {
+ getConnection(serverName);
+ return true;
+ } catch(ConnectionException e) {
+ return false;
+ }
+ }
+
+ public synchronized void installPublicKey(String serverName) {
+ Connection conn = getConnectionWithPassword(serverName);
+ SCPClient scpClient = new SCPClient(conn);
+
+ // delete file if it exists
+ File localTempFile = new File(TEMP_DIR + SSH_AUTHORIZED_KEYS_FILE);
+ if(localTempFile.exists()) {
+ localTempFile.delete();
+ }
+ try {
+
+ // get authorized_keys from server
+ scpClient.get(SSH_AUTHORIZED_KEYS_PATH, TEMP_DIR);
+ } catch (IOException e) {
+ // file doesn't exist. it will get created.
+ }
+
+ byte[] publicKeyData;
+ try {
+ publicKeyData = new FileUtil().readFileAsByteArray(PUBLIC_KEY_FILE);
+ } catch (Exception e) {
+ throw new GlusterRuntimeException("Couldn't load public key file [" + PUBLIC_KEY_FILE + "]", e);
+ }
+
+ try {
+ // append it
+ FileOutputStream outputStream = new FileOutputStream(localTempFile, true);
+ outputStream.write(CoreConstants.NEWLINE.getBytes());
+ outputStream.write(publicKeyData);
+ outputStream.close();
+ } catch (Exception e) {
+ throw new GlusterRuntimeException("Couldnt append file [" + localTempFile + "] with public key!", e);
+ }
+
+ try {
+ scpClient.put(localTempFile.getAbsolutePath(), SSH_AUTHORIZED_KEYS_FILE, SSH_AUTHORIZED_KEYS_DIR, "0600");
+ } catch (IOException e) {
+ throw new GlusterRuntimeException("Couldn't add public key to server [" + serverName + "]", e);
+ }
+ }
+
private Connection getConnectionWithPassword(String serverName) {
Connection conn = createConnection(serverName);
authenticateWithPassword(conn);
@@ -254,17 +323,4 @@ public class SshUtil {
conn.close();
}
}
-
- public static void main(String[] args) {
- SshUtil sshUtil = new SshUtil();
- System.out.println(new Date());
- ProcessResult result = sshUtil.executeRemote("dev.gluster.com", "/bin/pwd");
- System.out.println(result.getOutput());
- result = sshUtil.executeRemote("dev.gluster.com", "/bin/pwd1");
- System.out.println(new Date() + " - " + result.getExitValue() + " - " + result.getOutput());
- result = sshUtil.executeRemote("dev.gluster.com", "/bin/ls -lrt");
- System.out.println(new Date() + " - " + result.getExitValue() + " - " + result.getOutput());
-
- sshUtil.cleanup();
- }
}