summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShireesh Anjal <shireesh@gluster.com>2011-03-29 21:53:36 +0530
committerShireesh Anjal <shireesh@gluster.com>2011-03-29 21:53:36 +0530
commit5c39a47fdd3987bb5eee35f7f7397ce127c8919e (patch)
tree90c46009d9c1ac4ff8c43dbec5be0f40cef37afa
parent5ed821be2c54c9fbbbcbdc77a40edf4cc5454617 (diff)
Remote execution of scripts on peer machines from management server
-rw-r--r--src/com.gluster.storage.management.server.scripts/src/common/Globals.py5
-rwxr-xr-xsrc/com.gluster.storage.management.server.scripts/src/nodes/PeerAgent.py198
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java42
3 files changed, 243 insertions, 2 deletions
diff --git a/src/com.gluster.storage.management.server.scripts/src/common/Globals.py b/src/com.gluster.storage.management.server.scripts/src/common/Globals.py
index 365d4af7..9ae53491 100644
--- a/src/com.gluster.storage.management.server.scripts/src/common/Globals.py
+++ b/src/com.gluster.storage.management.server.scripts/src/common/Globals.py
@@ -52,7 +52,7 @@ SERVER_AGENT_PORT = 50000
BOOT_PARTITION_LABEL = "GLUSTEROS"
DATA_PARTITION_LABEL = "GLUSTERDATA"
VOLUME_USER_DESCRIPTION = "Gluster Volume User"
-SERVER_AGENT_RUN_USERNAME = "transport"
+SERVER_AGENT_RUN_USERNAME = "gluster"
INSTALLER_SERVER_NAME = "$installer$"
GLUSTER_BASE_DIR = "/GLUSTER"
@@ -64,7 +64,7 @@ WEBDAV_DOCUMENT_ROOT_DIR = "/var/www/html"
UPDATES_DIR = "/UPDATES"
TRANSPORT_HOME_DIR = "/transport"
GLUSTERFS_LOG_DIR = "/var/log/glusterfs"
-LOG_DIR = "/var/log/platform"
+LOG_DIR = "/var/log/glustermc"
GLUSTER_UPDATES_FILE = "updates.xml"
INSTALLER_STATUS_FILE = "/var/log/install-server-status.log"
@@ -103,6 +103,7 @@ SESSION_FILE = GLUSTER_TMP_DIR + "/login.sessions"
GENERAL_LOG_FILE = LOG_DIR + "/general.log"
INSTALLER_LOG_FILE = LOG_DIR + "/installer.log"
+PEER_AGENT_LOG_FILE = LOG_DIR + "/peeragent.log"
SERVER_AGENT_LOG_FILE = LOG_DIR + "/serveragent.log"
TRANSPORT_AGENT_LOG_FILE = LOG_DIR + "/transport.log"
##
diff --git a/src/com.gluster.storage.management.server.scripts/src/nodes/PeerAgent.py b/src/com.gluster.storage.management.server.scripts/src/nodes/PeerAgent.py
new file mode 100755
index 00000000..93c1f002
--- /dev/null
+++ b/src/com.gluster.storage.management.server.scripts/src/nodes/PeerAgent.py
@@ -0,0 +1,198 @@
+#!/usr/bin/python
+# Copyright (C) 2010 Gluster, Inc. <http://www.gluster.com>
+# This file is part of Gluster Storage Platform.
+#
+# Gluster Storage Platform 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 Storage Platform 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/>.
+
+import os
+import sys
+import signal
+import atexit
+import socket
+import syslog
+import pwd
+from optparse import OptionParser
+
+import Globals
+import Socket
+import Utils
+from XmlHandler import ResponseXml
+
+
+ME = os.path.basename(sys.argv[0])
+PID_FILE = "/var/run/serveragent.pid"
+serverSocket = None
+clientSocket = None
+clientAddress = None
+clientInputStream = None
+clientOutputStream = None
+
+
+def sigTermHandler(signal, frame):
+ sys.exit(0)
+
+
+def cleanup():
+ try:
+ if os.path.exists(PID_FILE):
+ os.unlink(PID_FILE)
+ except OSError, e:
+ Utils.log("Failed to remove PID file %s: %s" % (PID_FILE, str(e)))
+
+ try:
+ if clientSocket:
+ clientSocket.close()
+ except socket.error, e:
+ Utils.log("Failed to close client socket: %s" % str(e))
+
+ try:
+ if serverSocket:
+ serverSocket.close()
+ except socket.error, e:
+ Utils.log("Failed to close server socket: " % str(e))
+
+def stripEmptyLines(content):
+ ret = ""
+ for line in content.split("\n"):
+ if line.strip() != "":
+ ret += line
+ return ret
+
+def executeCommand(command):
+ rv = Utils.runCommandFG(command, stdout=True, root=True)
+ statusCode = rv["Status"]
+ if statusCode != 0:
+ rs = ResponseXml()
+ rs.appendTagRoute("status", statusCode);
+ rs.appendTagRoute("output", stripEmptyLines(rv["Stdout"]))
+ rs.appendTagRoute("error", stripEmptyLines(rv["Stderr"]))
+ print rs.toprettyxml()
+ return rs.toprettyxml()
+ else:
+ return rv["Stdout"]
+
+def main():
+ global PID_FILE
+ global serverSocket
+ global clientSocket
+ global clientAddress
+ global clientInputStream
+ global clientOutputStream
+
+ username = Globals.SERVER_AGENT_RUN_USERNAME
+
+ Utils.openLog(Globals.PEER_AGENT_LOG_FILE)
+
+ parser = OptionParser(version="%s %s" % (ME, Globals.GLUSTER_PLATFORM_VERSION))
+
+ parser.add_option("-N", "--no-daemon",
+ action="store_false", dest="daemonMode", default=True,
+ help="Run in foreground")
+ parser.add_option("-r", "--run-as", dest="username",
+ help="Run the daemon as USERNAME (default: %s)" % Globals.SERVER_AGENT_RUN_USERNAME,
+ metavar="USERNAME")
+ (options, args) = parser.parse_args()
+
+ if options.username:
+ username = options.username
+ try:
+ userInfo = pwd.getpwnam(username)
+ except KeyError, e:
+ sys.stderr.write("%s\n" % str(e))
+ serverSocket.close()
+ sys.exit(-1)
+ uid = userInfo.pw_uid
+ gid = userInfo.pw_gid
+
+ try:
+ Utils.log("__DEBUG__ Opening server socket on port %s" % Globals.SERVER_AGENT_PORT)
+ serverSocket = Socket.openServerSocket()
+ except socket.error, e:
+ sys.stderr.write("Failed to open server socket: %s\n" % str(e))
+ sys.exit(-1)
+
+ if options.daemonMode:
+ if os.path.exists(PID_FILE):
+ sys.stderr.write("fatal: %s file exists\n" % PID_FILE)
+ serverSocket.close()
+ sys.exit(-1)
+
+ if not Utils.daemonize():
+ sys.stderr.write("fatal: unable to run as daemon\n")
+ serverSocket.close()
+ sys.exit(-1)
+ try:
+ fp = open(PID_FILE, "w")
+ fp.write("%s\n" % os.getpid())
+ fp.close()
+ except IOError, e:
+ Utils.log("Pid file %s: %s" % (PID_FILE, str(e)))
+ serverSocket.close()
+ sys.exit(-1)
+ try:
+ os.chown(PID_FILE, uid, gid)
+ except OSError, e:
+ Utils.log("Pid file %s: %s" % (PID_FILE, str(e)))
+ serverSocket.close()
+ try:
+ os.unlink(PID_FILE)
+ except OSError, ex:
+ Utils.log("Failed to remove PID file %s: %s" % (PID_FILE, str(ex)))
+ sys.exit(-1)
+ else:
+ Globals.GLUSTER_DEBUG = True
+
+ try:
+ os.setregid(gid, gid)
+ except OSError, e:
+ Utils.log("Failed to set effective and real gid to %s: %s" % (gid, str(e)))
+ cleanup()
+ sys.exit(-1)
+ try:
+ os.setreuid(uid, uid)
+ except OSError, e:
+ Utils.log("Failed to set effective and real uid to %s: %s" % (uid, str(e)))
+ cleanup()
+ sys.exit(-1)
+
+ atexit.register(cleanup)
+ signal.signal(signal.SIGTERM, sigTermHandler)
+
+ while True:
+ Utils.log("__DEBUG__ Waiting for new connection on port %s" % Globals.SERVER_AGENT_PORT)
+ try:
+ clientSocket, clientAddress, clientInputStream, clientOutputStream = Socket.acceptClient(serverSocket)
+ except socket.error, e:
+ Utils.log("Failed to accept new connection: %s" % str(e))
+ sys.exit(-1)
+
+ Utils.log('__DEBUG__ Connected by %s' % str(clientAddress))
+ try:
+ requestString = Socket.readPacket(clientInputStream)
+ Utils.log('__DEBUG__ Received %s' % repr(requestString))
+ responseString = executeCommand(requestString)
+ if responseString:
+ Socket.writePacket(clientOutputStream, responseString)
+ clientOutputStream.flush()
+ else:
+ Utils.log('__DEBUG__ empty response string')
+ Utils.log('__DEBUG__ Closing client %s' % str(clientAddress))
+ clientSocket.close()
+ except socket.error, e:
+ Utils.log("Socket error on client: %s" % str(e))
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java
index 1d237461..b07873f1 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java
@@ -20,6 +20,11 @@
*/
package com.gluster.storage.management.server.utils;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
@@ -55,4 +60,41 @@ public class ServerUtil {
String scriptPath = servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName;
return scriptPath;
}
+
+ /**
+ * Executes given command on given server
+ *
+ * @param runInForeground
+ * @param serverName
+ * @param commandWithArgs
+ * @return Response from remote execution of the command
+ */
+ public String executeOnServer(boolean runInForeground, String serverName, String commandWithArgs) {
+ try {
+ InetAddress address = InetAddress.getByName(serverName);
+ Socket connection = new Socket(address, 50000);
+
+ PrintWriter writer = new PrintWriter(connection.getOutputStream(), true);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
+
+ writer.println(commandWithArgs);
+ writer.println(); // empty line means end of request
+
+ StringBuffer output = new StringBuffer();
+ String line;
+ while (!(line = reader.readLine()).trim().isEmpty()) {
+ output.append(line + CoreConstants.NEWLINE);
+ }
+
+ connection.close();
+ return output.toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static void main(String args[]) {
+ System.out.println(new ServerUtil().executeOnServer(true, "localhost", "ls -lrt"));
+ }
} \ No newline at end of file