import errno import os import re import time import chakana.command import chakana.error import chakana.shepherd import chakana.threads import chakana.utils from chakana.debug import * class Harness: def __init__(self, chakanaRoot, coojaTimeout, doCompile="True", withGUI="False"): self._chakanaRoot = os.path.abspath(chakanaRoot) self._coojaTimeout = coojaTimeout self._threadManager = chakana.threads.ThreadManager() self._doCompile = doCompile self._withGUI = withGUI debug(MajorEvent, "Chakana harness created") def start(self): port = self.startCooja() self._shepherd = chakana.shepherd.Shepherd(self._threadManager, port) def startCooja(self): # COMPILE COOJA AND PLUGIN if self._doCompile == "True": for target in ("cooja", "plugin"): buildCommand = 'cd ' + chakana.command.quote(self._chakanaRoot) + ' && ant compile_' + target debug(MajorEvent, "Building " + target) debug(Event, buildCommand) output = chakana.command.output(buildCommand) debug(MinorEvent, output) coojaOutputFile = os.path.join(self._chakanaRoot, "build/cooja.out") # START COOJA if os.path.isfile(coojaOutputFile): os.remove(coojaOutputFile) coojaThread = CoojaThread(self._threadManager, self._chakanaRoot, coojaOutputFile, self._coojaTimeout, withGUI=self._withGUI) coojaThread.start() return coojaThread.port() def shepherd(self): return self._shepherd def quit(self): self._shepherd.quit() def killAllProcesses(self): self._threadManager.killAll() def waitForAllThreads(self, timeout): self._threadManager.waitAll(timeout) class CoojaThread(chakana.threads.ManagedThread): def __init__(self, threadManager, chakanaRoot, outputFile, timeout = 3600, name = "COOJA", withGUI="False", ** kwArgs): chakana.threads.ManagedThread.__init__( self, threadManager, name = name, **kwArgs) self._chakanaRoot = chakanaRoot self._outputFile = outputFile self._timeout = timeout self._port = None self._withGUI = withGUI def doRun(self): debug(MajorEvent, "Starting COOJA") buildDir = os.path.dirname(self._outputFile) chakana.utils.makeDirsSafe(buildDir) contikiRoot = os.path.join(self._chakanaRoot, '../..') contikiRoot = contikiRoot.replace('/cygdrive/c', 'c:') if self._withGUI == "True": coojaCommand = '( cd ' + chakana.command.quote(buildDir) + ' && java -jar ' + \ chakana.command.quote(os.path.join(contikiRoot, 'tools/cooja/dist/cooja.jar')) + ' ' + \ '-external_tools_config=../cooja.chakana.properties ' + \ '-contiki=' + chakana.command.quote(contikiRoot) + ' < /dev/null > ' + \ os.path.basename(self._outputFile) + ' 2>&1 )' else: coojaCommand = '( cd ' + chakana.command.quote(buildDir) + ' && java -jar ' + \ chakana.command.quote(os.path.join(contikiRoot, 'tools/cooja/dist/cooja.jar')) + ' ' + \ '-nogui ' + \ '-external_tools_config=../cooja.chakana.properties ' + \ '-contiki=' + chakana.command.quote(contikiRoot) + ' < /dev/null > ' + \ os.path.basename(self._outputFile) + ' 2>&1 )' debug(Event, coojaCommand) os.system(coojaCommand) debug(MajorEvent, "COOJA has finished") def port(self): if self._port is None: laps = 0 debug(Event, "Waiting for COOJA to open server socket") debug(Debug, "Reading: " + self._outputFile) while 1: if self._timeout > 0 and laps > self._timeout: raise chakana.error.Timeout(self, self._timeout) logContents = "" try: logContents = chakana.utils.readFile(self._outputFile) except IOError, err: if err.errno != errno.ENOENT: raise match = re.search(r"Chakana server listening on port (\d+).", logContents) debug(Debug, "Log contents: " + logContents) if match: self._port = int(match.group(1)) debug(Event, "COOJA is now listening on port " + str(self._port)) break else: debug(Debug, "Waiting for COOJA to start") time.sleep(1) laps += 1 match = re.search(r"Unable to access jarfile", logContents) if match: raise RuntimeError("Could not locate COOJA JAR: " + logContents) return self._port