sudo = self._sudo_kill)
# TODO: check if execution errors occurred
- if proc.poll() or err:
+ if (proc and proc.poll()) or err:
msg = " Failed to STOP command '%s' " % self.get("command")
self.error(msg, out, err)
return self.send_msg(NS3WrapperMessage.GET, *args)
- def trace(self, *args):
- return self.send_msg(NS3WrapperMessage.TRACE, *args)
+ def enable_trace(self, *args):
+ return self.send_msg(NS3WrapperMessage.ENABLE_TRACE, *args)
+
+ def flush(self):
+ return self.send_msg(NS3WrapperMessage.FLUSH, [])
def start(self):
return self.send_msg(NS3WrapperMessage.START, [])
def stop(self, time = None):
- args = None
+ args = []
if time:
- args = [time]
+ args.append(time)
return self.send_msg(NS3WrapperMessage.STOP, *args)
@classmethod
def _register_attributes(cls):
ns_log = Attribute("nsLog",
- "NS_LOG environment variable ",
+ "NS_LOG environment variable. " \
+ " Will only generate output if ns-3 is compiled in DEBUG mode. ",
flags = Flags.Design)
verbose = Attribute("verbose",
return os.path.join("/", "tmp", self.socket_name)
+ def trace(self, name, attr = TraceAttr.ALL, block = 512, offset = 0):
+ self._client.flush()
+ return LinuxApplication.trace(self, name, attr, block, offset)
+
def upload_sources(self):
self.node.mkdir(os.path.join(self.node.src_dir, "ns3wrapper"))
self.info("Starting ns-3 simulation")
if self.state == ResourceState.READY:
+ self._client.start()
self.set_started()
else:
msg = " Failed to execute command '%s'" % command
"""
if self.state == ResourceState.STARTED:
- # TODO: Stop simulation
+ self._client.stop()
+ self._client.shutdown()
LinuxApplication.do_stop(self)
def do_release(self):
self.node.execute(tear_down)
self.do_stop()
-
- self._client.shutdown()
super(LinuxApplication, self).do_release()
ns_log = self.get("nsLog")
if ns_log:
command.append("-L %s" % ns_log)
+
if self.get("verbose"):
command.append("-v")
- command.append("-H")
- command.append(self.run_home)
-
command = " ".join(command)
return command
#
# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
-from nepi.execution.resource import clsinit_copy
+from nepi.execution.resource import clsinit_copy, ResourceState
from nepi.resources.ns3.ns3base import NS3Base
@clsinit_copy
self.simulation.invoke(node.uuid, "AddApplication", self.uuid)
self._connected.add(node.uuid)
-
def do_stop(self):
if self.state == ResourceState.STARTED:
# No need to do anything, simulation.Destroy() will stop every object
@property
def state(self):
- #if self._state == ResourceState.STARTED:
+ if self._state == ResourceState.STARTED:
+ is_running = self.simulation.invoke(self.uuid, "isAppRunning")
+ if not is_running:
+ self._state = ResourceState.STOPPED
return self._state
- """
- now = testbed_instance.ns3.Simulator.Now()
- if now.IsZero():
- return STATUS_NOT_STARTED
- app = testbed_instance.elements[guid]
- parameters = testbed_instance._get_parameters(guid)
- if "StartTime" in parameters and parameters["StartTime"]:
- start_value = parameters["StartTime"]
- start_time = testbed_instance.ns3.Time(start_value)
- if now.Compare(start_time) < 0:
- return STATUS_NOT_STARTED
- if "StopTime" in parameters and parameters["StopTime"]:
- stop_value = parameters["StopTime"]
- stop_time = testbed_instance.ns3.Time(stop_value)
- if now.Compare(stop_time) < 0:
- return STATUS_RUNNING
- else:
- return STATUS_FINISHED
- return STATUS_UNDETERMINED
- """
_rtype = "abstract::ns3::Object"
_backend_type = "ns3"
+ SIMULATOR_UUID = "singleton::Simulator"
+
def __init__(self, ec, guid):
super(NS3Base, self).__init__(ec, guid)
self._uuid = None
def trace(self, *args):
pass
+ def flush(self):
+ pass
+
def start(self):
pass
INVOKE = "INVOKE"
SET = "SET"
GET = "GET"
- TRACE = "TRACE"
+ ENABLE_TRACE = "ENABLE_TRACE"
+ FLUSH = "FLUSH"
START = "START"
STOP = "STOP"
SHUTDOWN = "SHUTDOWN"
uuid = args.pop(0)
operation = args.pop(0)
- ns3_wrapper.logger.debug("INVOKE %s %s %s" % (uuid, operation, str(args)))
+ ns3_wrapper.logger.debug("INVOKE %s %s %s " % (uuid, operation,
+ str(args)))
uuid = ns3_wrapper.invoke(uuid, operation, *args)
return uuid
name = args.pop(0)
value = args.pop(0)
- ns3_wrapper.logger.debug("SET %s %s" % (uuid, name, str(value)))
+ ns3_wrapper.logger.debug("SET %s %s %s" % (uuid, name, str(value)))
value = ns3_wrapper.set(uuid, name, value)
return value
- if msg == NS3WrapperMessage.TRACE:
- ns3_wrapper.logger.debug("TRACE")
- return "NOT IMPLEMENTED"
+ if msg == NS3WrapperMessage.ENABLE_TRACE:
+ ns3_wrapper.logger.debug("ENABLE_TRACE")
+
+ return "NOT YET IMPLEMENTED"
+
+ if msg == NS3WrapperMessage.FLUSH:
+ # Forces flushing output and error streams.
+ # NS-3 output will stay unflushed until the program exits or
+ # explicit invocation flush is done
+ sys.stdout.flush()
+ sys.stderr.flush()
+
+ ns3_wrapper.logger.debug("FLUSHED")
+
+ return "FLUSHED"
def create_socket(socket_name):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
conn.send("%s\n" % encoded)
def get_options():
- usage = ("usage: %prog -S <socket-name> -L <NS_LOG> -H <home_dir> -v ")
+ usage = ("usage: %prog -S <socket-name> -L <NS_LOG> -v ")
parser = OptionParser(usage = usage)
help = "NS_LOG environmental variable to be set",
default = "", type="str")
- parser.add_option("-H", "--homedir", dest="homedir",
- help = "Home directory where to store results",
- default = "", type="str")
-
parser.add_option("-v", "--verbose",
help="Print debug output",
action="store_true",
(options, args) = parser.parse_args()
- return (options.socket_name, options.homedir, options.verbose,
- options.ns_log)
+ return (options.socket_name, options.verbose, options.ns_log)
-def run_server(socket_name, homedir = None, level = logging.INFO,
- ns_log = None):
+def run_server(socket_name, level = logging.INFO, ns_log = None):
# Sets NS_LOG environmental variable for NS debugging
if ns_log:
###### ns-3 wrapper instantiation
- ns3_wrapper = NS3Wrapper(homedir = homedir, loglevel=level)
+ ns3_wrapper = NS3Wrapper(loglevel=level)
ns3_wrapper.logger.info("STARTING...")
if __name__ == '__main__':
- (socket_name, homedir, verbose, ns_log) = get_options()
+ (socket_name, verbose, ns_log) = get_options()
## configure logging
FORMAT = "%(asctime)s %(name)s %(levelname)-4s %(message)s"
logging.basicConfig(format = FORMAT, level = level)
- # Make sure to send DEBUG messages to stdout instead of stderr
- root = logging.getLogger()
- handler = logging.StreamHandler(sys.stdout)
- handler.setLevel(logging.DEBUG)
- root.addHandler(handler)
-
## Run the server
- run_server(socket_name, homedir, level, ns_log)
+ run_server(socket_name, level, ns_log)
def get(self, uuid, name):
return self.client.get(uuid, name)
- def trace(self, *args):
- return self.client.trace(*args)
+ def enable_trace(self, *args):
+ return self.client.enable_trace(*args)
+
+ def flush(self):
+ return self.client.flush()
def start(self):
return self.client.start()
return ns3mod
class NS3Wrapper(object):
- def __init__(self, homedir = None, loglevel = logging.INFO):
+ def __init__(self, loglevel = logging.INFO):
super(NS3Wrapper, self).__init__()
# Thread used to run the simulation
self._simulation_thread = None
self._condition = None
- # XXX: Started should be global. There is no support for more than
- # one simulator per process
+ # True if Simulator::Run was invoked
self._started = False
# holds reference to all C++ objects and variables in the simulation
self._objects = dict()
- # create home dir (where all simulation related files will end up)
- self._homedir = homedir or os.path.join("/", "tmp", "ns3_wrapper" )
-
- home = os.path.normpath(self.homedir)
- if not os.path.exists(home):
- os.makedirs(home, 0755)
-
# Logging
self._logger = logging.getLogger("ns3wrapper")
self._logger.setLevel(loglevel)
return self._allowed_types
- @property
- def homedir(self):
- return self._homedir
-
@property
def logger(self):
return self._logger
return uuid
def invoke(self, uuid, operation, *args):
+ if operation == "isAppRunning":
+ return self._is_app_running(uuid)
+
if uuid.startswith(SINGLETON):
obj = self._singleton(uuid)
else:
obj = self.get_object(uuid)
-
+
method = getattr(obj, operation)
# arguments starting with 'uuid' identify ns-3 C++
result = method(*realargs)
if not result:
- return None
-
+ return result
+
newuuid = self.make_uuid()
self._objects[newuuid] = result
# to set the value by scheduling an event, else
# we risk to corrupt the state of the
# simulation.
+
+ event_executed = [False]
+
if self.is_running:
# schedule the event in the Simulator
- self._schedule_event(self._condition, self._set_attr,
- obj, name, ns3_value)
- else:
+ self._schedule_event(self._condition, event_executed,
+ self._set_attr, obj, name, ns3_value)
+
+ if not event_executed[0]:
self._set_attr(obj, name, ns3_value)
return value
type_name = obj.GetInstanceTypeId().GetName()
ns3_value = self._create_attr_ns3_value(type_name, name)
+ event_executed = [False]
+
if self.is_running:
# schedule the event in the Simulator
- self._schedule_event(self._condition, self._get_attr, obj,
- name, ns3_value)
- else:
- get_attr(obj, name, ns3_value)
+ self._schedule_event(self._condition, event_executed,
+ self._get_attr, obj, name, ns3_value)
+
+ if not event_executed[0]:
+ self._get_attr(obj, name, ns3_value)
return self._attr_from_ns3_value_to_string(type_name, name, ns3_value)
#self.logger.debug("Waiting for simulation to finish")
time.sleep(0.5)
- # TODO!!!! SHOULD WAIT UNTIL THE THREAD FINISHES
if self._simulator_thread:
self._simulator_thread.join()
condition.notifyAll()
condition.release()
- def _schedule_event(self, condition, func, *args):
+ def _schedule_event(self, condition, event_executed, func, *args):
""" Schedules event on running simulation, and wait until
event is executed"""
- def execute_event(contextId, condition, has_event_occurred, func, *args):
+ def execute_event(contextId, condition, event_executed, func, *args):
try:
func(*args)
+ event_executed[0] = True
finally:
- # flag event occured
- has_event_occurred[0] = True
- # notify condition indicating attribute was set
+ # notify condition indicating event was executed
condition.acquire()
condition.notifyAll()
condition.release()
# delay 0 means that the event is expected to execute inmediately
delay = self.ns3.Seconds(0)
+
+ # Mark event as not executed
+ event_executed[0] = False
- # flag to indicate that the event occured
- # because bool is an inmutable object in python, in order to create a
- # bool flag, a list is used as wrapper
- has_event_occurred = [False]
condition.acquire()
-
- simu = self.ns3.Simulator
-
try:
- if not simu.IsFinished():
- simu.ScheduleWithContext(contextId, delay, execute_event,
- condition, has_event_occurred, func, *args)
- while not has_event_occurred[0] and not simu.IsFinished():
- condition.wait()
+ self.ns3.Simulator.ScheduleWithContext(contextId, delay, execute_event,
+ condition, event_executed, func, *args)
+ if not self.ns3.Simulator.IsFinished():
+ condition.wait()
finally:
condition.release()
return realargs
+ def _is_app_running(self, uuid):
+ now = self.ns3.Simulator.Now()
+ if now.IsZero():
+ return False
+
+ stop_value = self.get(uuid, "StopTime")
+ stop_time = self.ns3.Time(stop_value)
+
+ start_value = self.get(uuid, "StartTime")
+ start_time = self.ns3.Time(start_value)
+
+ if now.Compare(start_time) >= 0 and now.Compare(stop_time) <= 0:
+ return True
+
+ return False
+
import time
import unittest
+class DummySimulation(object):
+ def __init__(self, socket_name):
+ self.socket_name = socket_name
+ self.node = dict({'hostname': 'localhost'})
+
+ @property
+ def local_socket(self):
+ return self.socket_name
+
class LinuxNS3ClientTest(unittest.TestCase):
def setUp(self):
self.socket_name = os.path.join("/", "tmp", "NS3WrapperServer.sock")
# Verify that the communication socket was created
self.assertTrue(os.path.exists(self.socket_name))
+ # Create a dummy simulation object
+ simulation = DummySimulation(self.socket_name)
+
# Instantiate the NS3 client
- client = LinuxNS3Client(self.socket_name)
+ client = LinuxNS3Client(simulation)
# Define a real time simulation
stype = client.create("StringValue", "ns3::RealtimeSimulatorImpl")
# wait until simulation is over
client.shutdown()
+ ## TODO: Add assertions !!
if __name__ == '__main__':
unittest.main()
import unittest
class LinuxNS3ClientTest(unittest.TestCase):
- def test_runtime_attr_modify(self):
- ssh_key = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
+ def setUp(self):
+ self.fedora_host = "nepi2.pl.sophia.inria.fr"
+ #self.fedora_host = "peeramide.irisa.fr"
+ self.fedora_user = "inria_test"
+ def test_simple_ping(self):
ec = ExperimentController(exp_id = "test-ns3-simu")
node = ec.register_resource("LinuxNode")
- #ec.set(node, "hostname", "roseval.pl.sophia.inria.fr")
- #ec.set(node, "username", "alina")
- ec.set(node, "hostname", "peeramide.irisa.fr")
- #ec.set(node, "hostname", "planetlab2.upc.es")
- ec.set(node, "username", "inria_alina")
- ec.set(node, "identity", ssh_key)
+ ec.set(node, "hostname", self.fedora_host)
+ ec.set(node, "username", self.fedora_user)
ec.set(node, "cleanProcesses", True)
+ ec.set(node, "cleanHome", True)
simu = ec.register_resource("LinuxNS3Simulation")
ec.set(simu, "verbose", True)
+ ec.set(simu, "nsLog", "V4Ping:Node")
ec.register_connection(simu, node)
nsnode1 = ec.register_resource("ns3::Node")
ec.deploy()
- #time.sleep(60)
- ec.wait_started([ping])
- #ec.wait_finised([ping])
+ ec.wait_finished([ping])
+
+ stdout = ec.trace(simu, "stdout")
+
+ expected = "20 packets transmitted, 20 received, 0% packet loss"
+ self.assertTrue(stdout.find(expected) > -1)
ec.shutdown()
from nepi.resources.ns3.ns3wrapper import NS3Wrapper
+import StringIO
import subprocess
+import sys
import time
import unittest
p.communicate()
def test_start(self):
+ # Instantiate ns-3
wrapper = NS3Wrapper()
### create 2 nodes
# wait until simulation is over
wrapper.shutdown()
+ # TODO: Add assertions !!
+
def test_runtime_attr_modify(self):
wrapper = NS3Wrapper()
p = subprocess.Popen("rm /tmp/trace-p2p-*", shell = True)
p.communicate()
+
+ # TODO: Add assertions !!
if __name__ == '__main__':
unittest.main()