diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index 52b18c45..ba42a568 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -100,6 +100,22 @@ def mutedetach(*args, **kwds): kwds["stderr"] = subprocess.STDOUT return subprocess.Popen(*args, **kwds).pid +def cmdresult(args): + ''' Execute a command on the host and return a tuple containing the + exit status and result string. stderr output + is folded into the stdout result string. + ''' + cmdid = subprocess.Popen(args, stdin = subprocess.PIPE, + stdout = subprocess.PIPE, + stderr = subprocess.PIPE) + cmdid.stdin.close() + result = cmdid.stdout.read() + result += cmdid.stderr.read() + cmdid.stdout.close() + cmdid.stderr.close() + status = cmdid.wait() + return (status, result) + def hexdump(s, bytes_per_word = 2, words_per_line = 8): dump = "" count = 0 @@ -243,3 +259,16 @@ def readfileintodict(filename, d): d[key] = value.strip() except ValueError: pass + + +def checkforkernelmodule(name): + ''' Return a string if a Linux kernel module is loaded, None otherwise. + The string is the line from /proc/modules containing the module name, + memory size (bytes), number of loaded instances, dependencies, state, + and kernel memory offset. + ''' + with open('/proc/modules', 'r') as f: + for line in f: + if line[:len(name)] == name: + return line + return None diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index a3ea7a2d..bd50309f 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -34,7 +34,7 @@ except ImportError: from core.constants import * from core.api import coreapi from core.coreobj import PyCoreNet -from core.misc.utils import hexdump, daemonize +from core.misc.utils import hexdump, daemonize, cmdresult, mutedetach from core.misc.xmlutils import opensessionxml, savesessionxml DEFAULT_MAXFD = 1024 @@ -786,7 +786,8 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): exectime = msg.gettlv(coreapi.CORE_TLV_EXEC_TIME) cmd = msg.gettlv(coreapi.CORE_TLV_EXEC_CMD) - if nodenum is None: + # local flag indicates command executed locally, not on a node + if nodenum is None and not msg.flags & coreapi.CORE_API_LOC_FLAG: raise ValueError, "Execute Message is missing node number." if execnum is None: raise ValueError, "Execute Message is missing execution number." @@ -799,16 +800,23 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): except KeyError: # XXX wait and queue this message to try again later # XXX maybe this should be done differently - time.sleep(0.125) - self.queuemsg(msg) - return () + if not msg.flags & coreapi.CORE_API_LOC_FLAG: + time.sleep(0.125) + self.queuemsg(msg) + return () + else: + pass # build common TLV items for reply tlvdata = "" - tlvdata += coreapi.CoreExecTlv.pack(coreapi.CORE_TLV_EXEC_NODE, nodenum) + if nodenum is not None: + tlvdata += coreapi.CoreExecTlv.pack(coreapi.CORE_TLV_EXEC_NODE, + nodenum) tlvdata += coreapi.CoreExecTlv.pack(coreapi.CORE_TLV_EXEC_NUM, execnum) tlvdata += coreapi.CoreExecTlv.pack(coreapi.CORE_TLV_EXEC_CMD, cmd) if msg.flags & coreapi.CORE_API_TTY_FLAG: + if nodenum is None: + raise NotImplementedError # echo back exec message with cmd for spawning interactive terminal if cmd == "bash": cmd = "/bin/bash" @@ -825,7 +833,10 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if msg.flags & coreapi.CORE_API_STR_FLAG or \ msg.flags & coreapi.CORE_API_TXT_FLAG: # shlex.split() handles quotes within the string - status, res = n.cmdresult(shlex.split(cmd)) + if msg.flags & coreapi.CORE_API_LOC_FLAG: + status, res = cmdresult(shlex.split(cmd)) + else: + status, res = n.cmdresult(shlex.split(cmd)) if self.verbose: self.info("done exec cmd='%s' with status=%d res=(%d bytes)" % (cmd, status, len(res))) @@ -839,7 +850,10 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): return (reply, ) # execute the command with no response else: - n.cmd(shlex.split(cmd), wait=False) + if msg.flags & coreapi.CORE_API_LOC_FLAG: + mutedetach(shlex.split(cmd)) + else: + n.cmd(shlex.split(cmd), wait=False) return ()