diff --git a/build.xml b/build.xml index 766974b1124e0d8ac90709afd165f2856bb9a13c..3093f956856f9b2ca13bf9e67fe37d573ee1f609 100644 --- a/build.xml +++ b/build.xml @@ -28,6 +28,7 @@ <property name="test-output" location="${target}/test"/> <property name="source" location="src/main/java"/> <property name="source-test" location="src/test/java"/> + <property name="python-src" location="src/main/python"/> <property name="docs" location="${target}/docs"/> <property name="main-class" value="net.floodlightcontroller.core.internal.Controller"/> <property name="packetstreamer-gen" location="${target}/gen-java" /> @@ -51,6 +52,7 @@ <include name="netty-3.2.6.Final.jar"/> <include name="args4j-2.0.16.jar"/> <include name="concurrentlinkedhashmap-lru-1.2.jar"/> + <include name="jython-2.5.2.jar"/> </patternset> <patternset id="genlib"> <include name="libthrift-0.7.0.jar"/> @@ -157,6 +159,9 @@ <attribute name="Class-Path" value="."/> </manifest> <fileset dir="${build}"/> + <fileset dir="${python-src}"> + <include name="**/*.py"/> + </fileset> <zipgroupfileset dir="lib"> <patternset refid="lib"/> </zipgroupfileset> diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index e0f9ab823303c689cc47c374530cf2fac5e91acd..8a0563578286a9c5fabf1b283b10932423c1463d 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -66,6 +66,7 @@ import net.floodlightcontroller.counter.CounterStore.NetworkLayer; import net.floodlightcontroller.devicemanager.IDeviceManagerAware; import net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl; import net.floodlightcontroller.forwarding.Forwarding; +import net.floodlightcontroller.jython.Server; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.routing.dijkstra.RoutingImpl; @@ -1500,9 +1501,31 @@ public class Controller messageFilterManager.startUp(); log.debug("Starting staticFlowEntryPusher service"); staticFlowEntryPusher.startUp(); + log.debug("Starting DebugServer"); + this.debugserver_start(); } - /** + /** + * Start debug server, put global state as local variables for the jython shell + */ + protected void debugserver_start() { + Map<String, Object> locals = new HashMap<String, Object>(); + locals.put("controller", this); + locals.put("deviceManager", this.deviceManager); + locals.put("topology", this.topology); + locals.put("routingEngine", this.routingEngine); + locals.put("forwarding", this.forwarding); + locals.put("staticFlowEntryPusher", this.staticFlowEntryPusher); + locals.put("counterStore", this.counterStore); + locals.put("storageSource", this.storageSource); + locals.put("switches", this.switches); + locals.put("messageFilterManager", this.messageFilterManager); + + Server debug_server = new Server(6655, locals); + debug_server.start(); + } + + /** * Main function entry point; override init() for adding modules * @param args Command line arguments */ diff --git a/src/main/java/net/floodlightcontroller/jython/Server.java b/src/main/java/net/floodlightcontroller/jython/Server.java new file mode 100644 index 0000000000000000000000000000000000000000..8f17b9964bbb6d82cf1b267657c017cbdbada68c --- /dev/null +++ b/src/main/java/net/floodlightcontroller/jython/Server.java @@ -0,0 +1,30 @@ +package net.floodlightcontroller.jython; + +import java.util.Map; + +import org.python.util.PythonInterpreter; + +public class Server extends Thread { + int port; + Map<String, Object> locals; + + public Server(int port_, Map<String, Object> locals_) { + this.port = port_ ; + this.locals = locals_; + + } + + public void run() { + PythonInterpreter p = new PythonInterpreter(); + for (String name : this.locals.keySet()) { + p.set(name, this.locals.get(name)); + } + + String jarPath = Server.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + p.exec("import sys"); + p.exec("sys.path.append('" + jarPath + "')"); + p.exec("from debugserver import run_server"); + p.exec("run_server(" + this.port + ", '0.0.0.0', locals())"); + } + +} diff --git a/src/main/python/debugserver.py b/src/main/python/debugserver.py new file mode 100644 index 0000000000000000000000000000000000000000..2f6346f028a2bfacbfd6640a7acb7505ec74bb20 --- /dev/null +++ b/src/main/python/debugserver.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +import sys +from SocketServer import BaseRequestHandler, TCPServer +from code import InteractiveConsole + +_locals = None + +class DebugConsole(InteractiveConsole): + def __init__(self, request): + self.request = request + InteractiveConsole.__init__(self, _locals) + + def raw_input(self, prompt): + self.request.send(prompt) + data = self.request.recv(10000).rstrip() + if len(data) == 1 and ord(data[0]) == 4: + sys.exit() + return data + + def write(self, data): + self.request.send(str(data)) + + def write_nl(self, data): + self.write(str(data)+"\r\n") + +class DebugServerHandler(BaseRequestHandler): + def __init__(self, request, client_address, server): + print 'Open connection to DebugServer from: %s' % str(client_address) + BaseRequestHandler.__init__(self, request, client_address, server) + + def handle(self): + console = DebugConsole(self.request) + sys.displayhook = console.write_nl + console.interact('DebugServer') + self.request.close() + +class DebugServer(TCPServer): + def handle_error(self, request, client_address): + print 'Closing connection to DebugServer from: %s' % str(client_address) + request.close() + +def run_server(port=6655, host='0.0.0.0', locals=locals()): + global _locals + _locals = locals + + print "Starting DebugServer on port %d" % port + server = DebugServer(('', port), DebugServerHandler) + try: + server.serve_forever() + except KeyboardInterrupt: + pass + +if __name__ == "__main__": + run_server()