From ab601cf5f7775071e59c6bdbb3369889244f70a5 Mon Sep 17 00:00:00 2001 From: Alina Quereilhac Date: Mon, 3 Feb 2014 20:07:34 +0100 Subject: [PATCH] Adding linux ns3 server unit test --- setup.py | 1 + src/nepi/execution/attribute.py | 35 ++- src/nepi/execution/resource.py | 13 +- src/nepi/resources/all/collector.py | 8 +- src/nepi/resources/linux/application.py | 28 +-- src/nepi/resources/linux/ccn/ccncontent.py | 6 +- src/nepi/resources/linux/ccn/ccnd.py | 26 +- src/nepi/resources/linux/ccn/ccnping.py | 8 +- src/nepi/resources/linux/ccn/ccnpingserver.py | 6 +- src/nepi/resources/linux/ccn/ccnr.py | 54 ++--- src/nepi/resources/linux/ccn/fibentry.py | 10 +- src/nepi/resources/linux/interface.py | 14 +- src/nepi/resources/linux/mtr.py | 14 +- src/nepi/resources/linux/node.py | 16 +- src/nepi/resources/linux/nping.py | 28 +-- src/nepi/resources/linux/ns3/ns3client.py | 6 + src/nepi/resources/linux/ns3/ns3simulator.py | 222 +----------------- src/nepi/resources/linux/ping.py | 46 ++-- src/nepi/resources/linux/tcpdump.py | 66 +++--- src/nepi/resources/linux/traceroute.py | 8 +- src/nepi/resources/linux/udptest.py | 44 ++-- src/nepi/resources/linux/udptunnel.py | 8 +- src/nepi/resources/ns3/ns3application.py | 21 ++ src/nepi/resources/ns3/ns3base.py | 16 +- src/nepi/resources/ns3/ns3channel.py | 2 +- src/nepi/resources/ns3/ns3ipv4l3protocol.py | 4 +- src/nepi/resources/ns3/ns3netdevice.py | 10 +- src/nepi/resources/ns3/ns3node.py | 10 + src/nepi/resources/ns3/ns3queue.py | 2 +- src/nepi/resources/ns3/ns3server.py | 53 ++++- src/nepi/resources/ns3/ns3wrapper.py | 7 +- .../ns3/resource_manager_generator.py | 4 +- src/nepi/resources/omf/application.py | 6 +- src/nepi/resources/planetlab/node.py | 4 +- .../resources/planetlab/openvswitch/ovs.py | 8 +- .../planetlab/openvswitch/ovsport.py | 2 +- .../resources/planetlab/openvswitch/tunnel.py | 8 +- src/nepi/resources/planetlab/tap.py | 14 +- src/nepi/util/execfuncs.py | 18 +- test/resources/linux/ns3/ns3client.py | 2 + test/resources/linux/ns3/ns3simulator.py | 131 +++++++++++ 41 files changed, 501 insertions(+), 488 deletions(-) create mode 100644 test/resources/linux/ns3/ns3simulator.py diff --git a/setup.py b/setup.py index 27b0f9b1..e618057f 100755 --- a/setup.py +++ b/setup.py @@ -23,6 +23,7 @@ setup( "nepi.resources.linux.ns3", "nepi.resources.netns", "nepi.resources.ns3", + "nepi.resources.ns3.classes", "nepi.resources.omf", "nepi.resources.planetlab", "nepi.resources.planetlab.openvswitch", diff --git a/src/nepi/execution/attribute.py b/src/nepi/execution/attribute.py index 1e3bdde8..64a3d056 100644 --- a/src/nepi/execution/attribute.py +++ b/src/nepi/execution/attribute.py @@ -30,18 +30,24 @@ class Flags: """ Differents flags to characterize an attribute """ - # Attribute can be modified by the user - NoFlags = 0x00 - # Attribute is not modifiable by the user - ReadOnly = 0x01 - # Attribute is not modifiable by the user during runtime - ExecReadOnly = 0x02 - # Attribute is an access credential - # TODO REMOVE!!! - Credential = 0x04 + # Attribute value can not be read (it is hidden to the user) + NoRead = 1 # 1 + + # Attribute value can not be modified (it is not editable by the user) + NoWrite = 1 << 1 # 2 + + # Attribute value can be modified only before deployment + Design = 1 << 2 # 4 + + # Attribute value will be used only during the deployment face + Construct = 1 << 3 | Design # 8 + 4 + + # Attribute provides credentials to access resources + Credential = 1 << 4 | Design # 16 + 4 + # Attribute is a filter used to discover resources - # TODO REMOVE!!! - Filter = 0x08 + Filter = 1 << 5 | Design # 32 + 4 + class Attribute(object): """ @@ -85,12 +91,12 @@ class Attribute(object): """ def __init__(self, name, help, type = Types.String, - flags = Flags.NoFlags, default = None, allowed = None, + flags = None, default = None, allowed = None, range = None, set_hook = None): self._name = name self._help = help self._type = type - self._flags = flags + self._flags = flags or 0 self._allowed = allowed self._range = range self._default = self._value = default @@ -178,3 +184,6 @@ class Attribute(object): adequate validation""" return True + def has_changed(self): + """ Returns true if the value has changed from the default """ + return self.value != self.default diff --git a/src/nepi/execution/resource.py b/src/nepi/execution/resource.py index b4a0c882..f0fad39a 100644 --- a/src/nepi/execution/resource.py +++ b/src/nepi/execution/resource.py @@ -193,7 +193,7 @@ class ResourceManager(Logger): "the experiment. ", type = Types.Bool, default = True, - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(critical) @@ -678,6 +678,7 @@ class ResourceManager(Logger): rclass = ResourceFactory.get_resource_type(rtype) for guid in self.connections: rm = self.ec.get_resource(guid) + if not rtype or isinstance(rm, rclass): connected.append(rm) return connected @@ -1033,7 +1034,7 @@ def find_types(): path = os.path.dirname(nepi.resources.__file__) search_path.add(path) - types = [] + types = set() for importer, modname, ispkg in pkgutil.walk_packages(search_path, prefix = "nepi.resources."): @@ -1041,7 +1042,7 @@ def find_types(): loader = importer.find_module(modname) try: - # Notice: Repeated calls to load_module will act as a reload of teh module + # Notice: Repeated calls to load_module will act as a reload of the module if modname in sys.modules: module = sys.modules.get(modname) else: @@ -1060,10 +1061,7 @@ def find_types(): continue if issubclass(attr, ResourceManager): - if attr.get_rtype().lower().find("abstract") > -1: - continue - - types.append(attr) + types.add(attr) if not modname in sys.modules: sys.modules[modname] = module @@ -1077,4 +1075,3 @@ def find_types(): return types - diff --git a/src/nepi/resources/all/collector.py b/src/nepi/resources/all/collector.py index 0b6ad230..f13a3923 100644 --- a/src/nepi/resources/all/collector.py +++ b/src/nepi/resources/all/collector.py @@ -48,14 +48,14 @@ class Collector(ResourceManager): @classmethod def _register_attributes(cls): trace_name = Attribute("traceName", "Name of the trace to be collected", - flags = Flags.ExecReadOnly) + flags = Flags.Design) store_dir = Attribute("storeDir", "Path to local directory to store trace results", default = tempfile.gettempdir(), - flags = Flags.ExecReadOnly) + flags = Flags.Design) sub_dir = Attribute("subDir", "Sub directory to collect traces into", - flags = Flags.ExecReadOnly) + flags = Flags.Design) rename = Attribute("rename", "Name to give to the collected trace file", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(trace_name) cls._register_attribute(store_dir) diff --git a/src/nepi/resources/linux/application.py b/src/nepi/resources/linux/application.py index 5ae8f0b3..e287a8af 100644 --- a/src/nepi/resources/linux/application.py +++ b/src/nepi/resources/linux/application.py @@ -90,43 +90,43 @@ class LinuxApplication(ResourceManager): command = Attribute("command", "Command to execute at application start. " "Note that commands will be executed in the ${RUN_HOME} directory, " "make sure to take this into account when using relative paths. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) forward_x11 = Attribute("forwardX11", "Enables X11 forwarding for SSH connections", - flags = Flags.ExecReadOnly) + flags = Flags.Design) env = Attribute("env", "Environment variables string for command execution", - flags = Flags.ExecReadOnly) + flags = Flags.Design) sudo = Attribute("sudo", "Run with root privileges", - flags = Flags.ExecReadOnly) + flags = Flags.Design) depends = Attribute("depends", "Space-separated list of packages required to run the application", - flags = Flags.ExecReadOnly) + flags = Flags.Design) sources = Attribute("sources", "Space-separated list of regular files to be uploaded to ${SRC} " "directory prior to building. Archives won't be expanded automatically. " "Sources are globally available for all experiments unless " "cleanHome is set to True (This will delete all sources). ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) files = Attribute("files", "Space-separated list of regular miscellaneous files to be uploaded " "to ${SHARE} directory. " "Files are globally available for all experiments unless " "cleanHome is set to True (This will delete all files). ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) libs = Attribute("libs", "Space-separated list of libraries (e.g. .so files) to be uploaded " "to ${LIB} directory. " "Libraries are globally available for all experiments unless " "cleanHome is set to True (This will delete all files). ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) bins = Attribute("bins", "Space-separated list of binary files to be uploaded " "to ${BIN} directory. " "Binaries are globally available for all experiments unless " "cleanHome is set to True (This will delete all files). ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) code = Attribute("code", "Plain text source code to be uploaded to the ${APP_HOME} directory. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) build = Attribute("build", "Build commands to execute after deploying the sources. " "Sources are uploaded to the ${SRC} directory and code " @@ -135,16 +135,16 @@ class LinuxApplication(ResourceManager): "./configure && make && make clean.\n" "Make sure to make the build commands return with a nonzero exit " "code on error.", - flags = Flags.ReadOnly) + flags = Flags.Design) install = Attribute("install", "Commands to transfer built files to their final destinations. " "Install commands are executed after build commands. ", - flags = Flags.ReadOnly) + flags = Flags.Design) stdin = Attribute("stdin", "Standard input for the 'command'", - flags = Flags.ExecReadOnly) + flags = Flags.Design) tear_down = Attribute("tearDown", "Command to be executed just before " "releasing the resource", - flags = Flags.ReadOnly) + flags = Flags.Design) cls._register_attribute(command) cls._register_attribute(forward_x11) diff --git a/src/nepi/resources/linux/ccn/ccncontent.py b/src/nepi/resources/linux/ccn/ccncontent.py index 84f61857..d23ca372 100644 --- a/src/nepi/resources/linux/ccn/ccncontent.py +++ b/src/nepi/resources/linux/ccn/ccncontent.py @@ -34,11 +34,11 @@ class LinuxCCNContent(LinuxApplication): def _register_attributes(cls): content_name = Attribute("contentName", "The name of the content to publish (e.g. ccn:/VIDEO) ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) content = Attribute("content", "The content to publish. It can be a path to a file or plain text ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) scope = Attribute("scope", "Use the given scope on the start-write request (if -r specified). " @@ -46,7 +46,7 @@ class LinuxCCNContent(LinuxApplication): "Note that a scope of 3 is encoded as the absence of any scope in the interest. ", type = Types.Integer, default = 1, - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(content_name) cls._register_attribute(content) diff --git a/src/nepi/resources/linux/ccn/ccnd.py b/src/nepi/resources/linux/ccn/ccnd.py index d8a3fc39..b32937a9 100644 --- a/src/nepi/resources/linux/ccn/ccnd.py +++ b/src/nepi/resources/linux/ccn/ccnd.py @@ -50,56 +50,56 @@ class LinuxCCND(LinuxApplication): " -1 - max logging \n" " Or apply bitwise OR to these values to get combinations of them", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) port = Attribute("port", "Sets the CCN_LOCAL_PORT environmental variable. " "Defaults to 9695 ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) sockname = Attribute("sockname", "Sets the CCN_LOCAL_SCOKNAME environmental variable. " "Defaults to /tmp/.ccnd.sock", - flags = Flags.ExecReadOnly) + flags = Flags.Design) capacity = Attribute("capacity", "Sets the CCND_CAP environmental variable. " "Capacity limit in terms of ContentObjects", - flags = Flags.ExecReadOnly) + flags = Flags.Design) mtu = Attribute("mtu", "Sets the CCND_MTU environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) data_pause = Attribute("dataPauseMicrosec", "Sets the CCND_DATA_PAUSE_MICROSEC environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) default_stale = Attribute("defaultTimeToStale", "Sets the CCND_DEFAULT_TIME_TO_STALE environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) max_stale = Attribute("maxTimeToStale", "Sets the CCND_MAX_TIME_TO_STALE environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) max_rte = Attribute("maxRteMicrosec", "Sets the CCND_MAX_RTE_MICROSEC environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) keystore = Attribute("keyStoreDirectory", "Sets the CCND_KEYSTORE_DIRECTORY environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) listen_on = Attribute("listenOn", "Sets the CCND_LISTEN_ON environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) autoreg = Attribute("autoreg", "Sets the CCND_AUTOREG environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) prefix = Attribute("prefix", "Sets the CCND_PREFIX environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(debug) cls._register_attribute(port) diff --git a/src/nepi/resources/linux/ccn/ccnping.py b/src/nepi/resources/linux/ccn/ccnping.py index f654a2ab..cbe599e1 100644 --- a/src/nepi/resources/linux/ccn/ccnping.py +++ b/src/nepi/resources/linux/ccn/ccnping.py @@ -34,21 +34,21 @@ class LinuxCCNPing(LinuxCCNPingServer): interval = Attribute("i", "Set ping interval in seconds (minimum 0.10 second) ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) count = Attribute("c", "Total number of pings", type = Types.Double, - flags = Flags.ExecReadOnly) + flags = Flags.Design) number = Attribute("n", "Set the starting number, the number is incremented by 1 after each Interest ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) prefix = Attribute("prefix", "Prefix to serve content (e.g. ccnx:/name/prefix)", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(interval) cls._register_attribute(count) diff --git a/src/nepi/resources/linux/ccn/ccnpingserver.py b/src/nepi/resources/linux/ccn/ccnpingserver.py index 2dee4db2..865b104c 100644 --- a/src/nepi/resources/linux/ccn/ccnpingserver.py +++ b/src/nepi/resources/linux/ccn/ccnpingserver.py @@ -35,16 +35,16 @@ class LinuxCCNPingServer(LinuxCCNApplication): "Run ccnping server as a daemon in background", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) freshness = Attribute("x", "Set FreshnessSeconds", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) prefix = Attribute("prefix", "Prefix to serve content (e.g. ccnx:/name/prefix)", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(daemon) cls._register_attribute(freshness) diff --git a/src/nepi/resources/linux/ccn/ccnr.py b/src/nepi/resources/linux/ccn/ccnr.py index e65779aa..6b0aa6fc 100644 --- a/src/nepi/resources/linux/ccn/ccnr.py +++ b/src/nepi/resources/linux/ccn/ccnr.py @@ -35,23 +35,23 @@ class LinuxCCNR(LinuxApplication): def _register_attributes(cls): max_fanout = Attribute("maxFanout", "Sets the CCNR_BTREE_MAX_FANOUT environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) max_leaf_entries = Attribute("maxLeafEntries", "Sets the CCNR_BTREE_MAX_LEAF_ENTRIES environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) max_node_bytes = Attribute("maxNodeBytes", "Sets the CCNR_BTREE_MAX_NODE_BYTES environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) max_node_pool = Attribute("maxNodePool", "Sets the CCNR_BTREE_MAX_NODE_POOL environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) content_cache = Attribute("contentCache", "Sets the CCNR_CONTENT_CACHE environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) debug = Attribute("debug", "Sets the CCNR_DEBUG environmental variable. " @@ -64,92 +64,92 @@ class LinuxCCNR(LinuxApplication): "WARNING", "INFO", "FINE, FINER, FINEST"], - flags = Flags.ExecReadOnly) + flags = Flags.Design) directory = Attribute("directory", "Sets the CCNR_DIRECTORY environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) global_prefix = Attribute("globalPrefix", "Sets the CCNR_GLOBAL_PREFIX environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) listen_on = Attribute("listenOn", "Sets the CCNR_LISTEN_ON environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) min_send_bufsize = Attribute("minSendBufsize", "Sets the CCNR_MIN_SEND_BUFSIZE environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) proto = Attribute("proto", "Sets the CCNR_PROTO environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) status_port = Attribute("statusPort", "Sets the CCNR_STATUS_PORT environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) start_write_scope_limit = Attribute("startWriteScopeLimit", "Sets the CCNR_START_WRITE_SCOPE_LIMIT environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_debug = Attribute("ccnsDebug", "Sets the CCNS_DEBUG environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_enable = Attribute("ccnsEnable", "Sets the CCNS_ENABLE environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_faux_error = Attribute("ccnsFauxError", "Sets the CCNS_FAUX_ERROR environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_heartbeat_micros = Attribute("ccnsHeartBeatMicros", "Sets the CCNS_HEART_BEAT_MICROS environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_max_compares_busy = Attribute("ccnsMaxComparesBusy", "Sets the CCNS_MAX_COMPARES_BUSY environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_max_fetch_busy = Attribute("ccnsMaxFetchBusy", "Sets the CCNS_MAX_FETCH_BUSY environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_node_fetch_lifetime = Attribute("ccnsNodeFetchLifetime", "Sets the CCNS_NODE_FETCH_LIFETIME environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_note_err = Attribute("ccnsNoteErr", "Sets the CCNS_NOTE_ERR environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_repo_store = Attribute("ccnsRepoStore", "Sets the CCNS_REPO_STORE environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_root_advise_fresh = Attribute("ccnsRootAdviseFresh", "Sets the CCNS_ROOT_ADVISE_FRESH environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_root_advise_lifetime = Attribute("ccnsRootAdviseLifetime", "Sets the CCNS_ROOT_ADVISE_LIFETIME environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_stable_enabled = Attribute("ccnsStableEnabled", "Sets the CCNS_STABLE_ENABLED environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ccns_sync_scope = Attribute("ccnsSyncScope", "Sets the CCNS_SYNC_SCOPE environmental variable. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) repo_file = Attribute("repoFile1", "The Repository uses $CCNR_DIRECTORY/repoFile1 for " "persistent storage of CCN Content Objects", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(max_fanout) cls._register_attribute(max_leaf_entries) diff --git a/src/nepi/resources/linux/ccn/fibentry.py b/src/nepi/resources/linux/ccn/fibentry.py index cebc1054..31272f3b 100644 --- a/src/nepi/resources/linux/ccn/fibentry.py +++ b/src/nepi/resources/linux/ccn/fibentry.py @@ -42,7 +42,7 @@ class LinuxFIBEntry(LinuxApplication): uri = Attribute("uri", "URI prefix to match and route for this FIB entry", default = "ccnx:/", - flags = Flags.ExecReadOnly) + flags = Flags.Design) protocol = Attribute("protocol", "Transport protocol used in network connection to peer " @@ -50,20 +50,20 @@ class LinuxFIBEntry(LinuxApplication): type = Types.Enumerate, default = "udp", allowed = ["udp", "tcp"], - flags = Flags.ExecReadOnly) + flags = Flags.Design) host = Attribute("host", "Peer hostname used in network connection for this FIB entry. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) port = Attribute("port", "Peer port address used in network connection to peer " "for this FIB entry.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ip = Attribute("ip", "Peer host public IP used in network connection for this FIB entry. ", - flags = Flags.ReadOnly) + flags = Flags.Design) cls._register_attribute(uri) cls._register_attribute(protocol) diff --git a/src/nepi/resources/linux/interface.py b/src/nepi/resources/linux/interface.py index 7b8eadc9..795c4d5d 100644 --- a/src/nepi/resources/linux/interface.py +++ b/src/nepi/resources/linux/interface.py @@ -42,33 +42,33 @@ class LinuxInterface(ResourceManager): @classmethod def _register_attributes(cls): ip4 = Attribute("ip4", "IPv4 Address", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ip6 = Attribute("ip6", "IPv6 Address", - flags = Flags.ExecReadOnly) + flags = Flags.Design) mac = Attribute("mac", "MAC Address", - flags = Flags.ExecReadOnly) + flags = Flags.Design) mask4 = Attribute("mask4", "IPv4 network mask", - flags = Flags.ExecReadOnly) + flags = Flags.Design) mask6 = Attribute("mask6", "IPv6 network mask", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) mtu = Attribute("mtu", "Maximum transmition unit for device", type = Types.Integer) devname = Attribute("deviceName", "Name of the network interface (e.g. eth0, wlan0, etc)", - flags = Flags.ExecReadOnly) + flags = Flags.Design) up = Attribute("up", "Link up", type = Types.Bool) tear_down = Attribute("tearDown", "Bash script to be executed before " + \ "releasing the resource", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(ip4) cls._register_attribute(ip6) diff --git a/src/nepi/resources/linux/mtr.py b/src/nepi/resources/linux/mtr.py index 1edc6b53..b6944439 100644 --- a/src/nepi/resources/linux/mtr.py +++ b/src/nepi/resources/linux/mtr.py @@ -34,41 +34,41 @@ class LinuxMtr(LinuxApplication): "sets mtr --report-cycles (-c) option. Determines the number of " "pings sent to determine both machines in the networks. Each " "cycle lasts one sencond.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) no_dns = Attribute("noDns", "sets mtr --no-dns (-n) option. Forces mtr to display IPs intead of " "trying to resolve to host names ", type = Types.Bool, default = True, - flags = Flags.ExecReadOnly) + flags = Flags.Design) address = Attribute("address", "sets mtr --address (-a) option. Binds the socket to send outgoing " "packets to the interface of the specified address, so that any " "any packets are sent through this interface. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) interval = Attribute("interval", "sets mtr --interval (-i) option. Specifies the number of seconds " "between ICMP ECHO requests. Default value is one second ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) countinuous = Attribute("continuous", "Run mtr in a while loop", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) print_timestamp = Attribute("printTimestamp", "Print timestamp before running mtr", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) target = Attribute("target", "mtr target host (host that will be pinged)", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(report_cycles) cls._register_attribute(no_dns) diff --git a/src/nepi/resources/linux/node.py b/src/nepi/resources/linux/node.py index 710561bf..4e162ce4 100644 --- a/src/nepi/resources/linux/node.py +++ b/src/nepi/resources/linux/node.py @@ -149,44 +149,44 @@ class LinuxNode(ResourceManager): @classmethod def _register_attributes(cls): hostname = Attribute("hostname", "Hostname of the machine", - flags = Flags.ExecReadOnly) + flags = Flags.Design) username = Attribute("username", "Local account username", flags = Flags.Credential) - port = Attribute("port", "SSH port", flags = Flags.ExecReadOnly) + port = Attribute("port", "SSH port", flags = Flags.Design) home = Attribute("home", "Experiment home directory to store all experiment related files", - flags = Flags.ExecReadOnly) + flags = Flags.Design) identity = Attribute("identity", "SSH identity file", flags = Flags.Credential) server_key = Attribute("serverKey", "Server public key", - flags = Flags.ExecReadOnly) + flags = Flags.Design) clean_home = Attribute("cleanHome", "Remove all nepi files and directories " " from node home folder before starting experiment", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) clean_experiment = Attribute("cleanExperiment", "Remove all files and directories " " from a previous same experiment, before the new experiment starts", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) clean_processes = Attribute("cleanProcesses", "Kill all running processes before starting experiment", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) tear_down = Attribute("tearDown", "Bash script to be executed before " + \ "releasing the resource", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(hostname) cls._register_attribute(username) diff --git a/src/nepi/resources/linux/nping.py b/src/nepi/resources/linux/nping.py index 62bacd89..544b4d9d 100644 --- a/src/nepi/resources/linux/nping.py +++ b/src/nepi/resources/linux/nping.py @@ -34,84 +34,84 @@ class LinuxNPing(LinuxApplication): "Sets nping -c option. " "Stop after a given number of rounds. ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) e = Attribute("e", "Sets nping -e option. " "Set the network interface to be used.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) delay = Attribute("delay", "Sets nping --delay option. " "Delay between probes ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) rate = Attribute("rate", "Sets nping --rate option. " "Send probes at a given rate ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ttl = Attribute("ttl", "Sets nping --ttl option. " "Time To Live. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) p = Attribute("p", "Sets nping -p option. " "Target ports. ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) tcp = Attribute("tcp", "Sets nping --tcp option. " "TCP mode. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) udp = Attribute("udp", "Sets nping --udp option. " "UDP mode. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) icmp = Attribute("icmp", "Sets nping --icmp option. " "ICMP mode. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) arp = Attribute("arp", "Sets nping --arp option. " "ARP mode. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) traceroute = Attribute("traceroute", "Sets nping --traceroute option. " "Traceroute mode. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) countinuous = Attribute("continuous", "Run nping in a while loop", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) print_timestamp = Attribute("printTimestamp", "Print timestamp before running nping", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) target = Attribute("target", "nping target host (host that will be pinged)", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(c) cls._register_attribute(e) diff --git a/src/nepi/resources/linux/ns3/ns3client.py b/src/nepi/resources/linux/ns3/ns3client.py index 972e8005..3fe5b99c 100644 --- a/src/nepi/resources/linux/ns3/ns3client.py +++ b/src/nepi/resources/linux/ns3/ns3client.py @@ -58,6 +58,12 @@ class LinuxNS3Client(NS3Client): return self.send_msg(NS3WrapperMessage.CREATE, *args) + def factory(self, type_name, **kwargs): + args = [type_name] + args.append(kwargs) + + return self.send_msg(NS3WrapperMessage.FACTORY, *args) + def invoke(self, uuid, operation, *args): args = list(args) args.insert(0, operation) diff --git a/src/nepi/resources/linux/ns3/ns3simulator.py b/src/nepi/resources/linux/ns3/ns3simulator.py index e4fda7eb..90edbc59 100644 --- a/src/nepi/resources/linux/ns3/ns3simulator.py +++ b/src/nepi/resources/linux/ns3/ns3simulator.py @@ -22,7 +22,6 @@ from nepi.execution.trace import Trace, TraceAttr from nepi.execution.resource import ResourceManager, clsinit_copy, \ ResourceState, reschedule_delay from nepi.resources.linux.application import LinuxApplication -from nepi.resources.linux.node import OSType from nepi.util.timefuncs import tnow, tdiffsec from nepi.resources.ns3.ns3simulator import NS3Simulator from nepi.resources.linux.ns3.ns3client import LinuxNS3Client @@ -35,21 +34,18 @@ class LinuxNS3Simulator(LinuxApplication, NS3Simulator): @classmethod def _register_attributes(cls): - max_rte = Attribute("maxRteMicrosec", - "Sets the CCND_MAX_RTE_MICROSEC environmental variable. ", - flags = Flags.ExecReadOnly) + socket_name = Attribute("socketName", + "Local socket name to communicate with the ns-3 server ", + flags = Flags.Design) - cls._register_attribute(max_rte) + cls._register_attribute(socket_name) def __init__(self, ec, guid): super(LinuxApplication, self).__init__(ec, guid) super(NS3Simulator, self).__init__() + self._client = None self._home = "ns3-simu-%s" % self.guid - - # TODO: Create socket!! - self._client = LinuxNS3Client(socket_name) - def do_deploy(self): if not self.node or self.node.state < ResourceState.READY: @@ -58,212 +54,14 @@ class LinuxNS3Simulator(LinuxApplication, NS3Simulator): # ccnd needs to wait until node is deployed and running self.ec.schedule(reschedule_delay, self.deploy) else: - if not self.get("command"): - self.set("command", self._start_command) - if not self.get("depends"): - self.set("depends", self._dependencies) - - if not self.get("sources"): - self.set("sources", self._sources) - - sources = self.get("sources") - source = sources.split(" ")[0] - basename = os.path.basename(source) - self._version = ( basename.strip().replace(".tar.gz", "") - .replace(".tar","") - .replace(".gz","") - .replace(".zip","") ) - - if not self.get("build"): - self.set("build", self._build) - - if not self.get("install"): - self.set("install", self._install) + # TODO: Create socket!! + socket_name = self.get("socketName") + self._client = LinuxNS3Client(socket_name) - if not self.get("env"): - self.set("env", self._environment) - - command = self.get("command") - - self.info("Deploying command '%s' " % command) - - self.do_discover() - self.do_provision() + #self.do_discover() + #self.do_provision() self.debug("----- READY ---- ") self.set_ready() - def upload_start_command(self): - command = self.get("command") - env = self.get("env") - - # We want to make sure the ccnd is running - # before the experiment starts. - # Run the command as a bash script in background, - # in the host ( but wait until the command has - # finished to continue ) - env = self.replace_paths(env) - command = self.replace_paths(command) - - shfile = os.path.join(self.app_home, "start.sh") - self.node.run_and_wait(command, self.run_home, - shfile = shfile, - overwrite = False, - env = env, - raise_on_error = True) - - def do_start(self): - if self.state == ResourceState.READY: - command = self.get("command") - self.info("Starting command '%s'" % command) - - self.set_started() - else: - msg = " Failed to execute command '%s'" % command - self.error(msg, out, err) - raise RuntimeError, msg - - def do_stop(self): - command = self.get('command') or '' - - if self.state == ResourceState.STARTED: - self.info("Stopping command '%s'" % command) - - command = "ccndstop" - env = self.get("env") - - # replace application specific paths in the command - command = self.replace_paths(command) - env = env and self.replace_paths(env) - - # Upload the command to a file, and execute asynchronously - shfile = os.path.join(self.app_home, "stop.sh") - self.node.run_and_wait(command, self.run_home, - shfile = shfile, - overwrite = False, - env = env, - pidfile = "ccndstop_pidfile", - ecodefile = "ccndstop_exitcode", - stdout = "ccndstop_stdout", - stderr = "ccndstop_stderr") - - self.set_stopped() - - @property - def state(self): - # First check if the ccnd has failed - state_check_delay = 0.5 - if self._state == ResourceState.STARTED and \ - tdiffsec(tnow(), self._last_state_check) > state_check_delay: - (out, err), proc = self._ccndstatus() - - retcode = proc.poll() - - if retcode == 1 and err.find("No such file or directory") > -1: - # ccnd is not running (socket not found) - self.set_stopped() - elif retcode: - # other errors ... - msg = " Failed to execute command '%s'" % self.get("command") - self.error(msg, out, err) - self.fail() - - self._last_state_check = tnow() - - return self._state - - def _ccndstatus(self): - env = self.get('env') or "" - environ = self.node.format_environment(env, inline = True) - command = environ + " ccndstatus" - command = self.replace_paths(command) - - return self.node.execute(command) - - @property - def _start_command(self): - return "ccndstart" - - @property - def _dependencies(self): - if self.node.use_rpm: - return ( " autoconf openssl-devel expat-devel libpcap-devel " - " ecryptfs-utils-devel libxml2-devel automake gawk " - " gcc gcc-c++ git pcre-devel make ") - elif self.node.use_deb: - return ( " autoconf libssl-dev libexpat-dev libpcap-dev " - " libecryptfs0 libxml2-utils automake gawk gcc g++ " - " git-core pkg-config libpcre3-dev make ") - return "" - - @property - def _sources(self): - return "http://www.ccnx.org/releases/ccnx-0.7.2.tar.gz" - - @property - def _build(self): - sources = self.get("sources").split(" ")[0] - sources = os.path.basename(sources) - - return ( - # Evaluate if ccnx binaries are already installed - " ( " - " test -f ${BIN}/%(version)s/ccnd && " - " echo 'binaries found, nothing to do' " - " ) || ( " - # If not, untar and build - " ( " - " mkdir -p ${SRC}/%(version)s && " - " tar xf ${SRC}/%(sources)s --strip-components=1 -C ${SRC}/%(version)s " - " ) && " - "cd ${SRC}/%(version)s && " - # Just execute and silence warnings... - " ( ./configure && make ) " - " )") % ({ 'sources': sources, - 'version': self.version - }) - - @property - def _install(self): - return ( - # Evaluate if ccnx binaries are already installed - " ( " - " test -f ${BIN}/%(version)s/ccnd && " - " echo 'binaries found, nothing to do' " - " ) || ( " - # If not, install - " mkdir -p ${BIN}/%(version)s && " - " mv ${SRC}/%(version)s/bin/* ${BIN}/%(version)s/ " - " )" - ) % ({ 'version': self.version - }) - - @property - def _environment(self): - envs = dict({ - "debug": "CCND_DEBUG", - "port": "CCN_LOCAL_PORT", - "sockname" : "CCN_LOCAL_SOCKNAME", - "capacity" : "CCND_CAP", - "mtu" : "CCND_MTU", - "dataPauseMicrosec" : "CCND_DATA_PAUSE_MICROSEC", - "defaultTimeToStale" : "CCND_DEFAULT_TIME_TO_STALE", - "maxTimeToStale" : "CCND_MAX_TIME_TO_STALE", - "maxRteMicrosec" : "CCND_MAX_RTE_MICROSEC", - "keyStoreDirectory" : "CCND_KEYSTORE_DIRECTORY", - "listenOn" : "CCND_LISTEN_ON", - "autoreg" : "CCND_AUTOREG", - "prefix" : "CCND_PREFIX", - }) - - env = self.path - env += " ".join(map(lambda k: "%s=%s" % (envs.get(k), str(self.get(k))) \ - if self.get(k) else "", envs.keys())) - - return env - - def valid_connection(self, guid): - # TODO: Validate! - return True - diff --git a/src/nepi/resources/linux/ping.py b/src/nepi/resources/linux/ping.py index 6db0a8d7..a3df5799 100644 --- a/src/nepi/resources/linux/ping.py +++ b/src/nepi/resources/linux/ping.py @@ -34,56 +34,56 @@ class LinuxPing(LinuxApplication): "Sets ping -c option. Determines the number of ECHO_REQUEST " "packates to send before stopping.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) mark = Attribute("mark", "Sets ping -m option. Uses 'mark' to tag outgoing packets. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) interval = Attribute("interval", "Sets ping -i option. Leaves interval seconds between " "successive ECHO_REUQEST packets. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) address = Attribute("address", "Sets ping -I option. Sets ECHO_REQUEST packets souce address " "to the specified interface address ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) preload = Attribute("preload", "Sets ping -l option. Sends preload amount of packets " "without waiting for a reply ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) numeric = Attribute("numeric", "Sets ping -n option. Disables resolution of host addresses into " "symbolic names. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) pattern = Attribute("pattern", "Sets ping -p option. Species a up to 16 ''pad'' bytes to fill " "out sent packets. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) printtmp = Attribute("printTimestamp", "Sets ping -D option. Prints timestamp befor each line as: " "unix time + microseconds as in gettimeofday ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) tos = Attribute("tos", "Sets ping -Q option. Sets Quality of Service related bits in ICMP " "datagrams. tos can be either a decimal or hexadecime number ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) quiet = Attribute("quiet", "Sets ping -q option. Disables ping standard output ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) rec_route = Attribute("recordRoute", "Sets ping -R option. Includes the RECORD_ROUTE option in the " @@ -91,37 +91,37 @@ class LinuxPing(LinuxApplication): "ping standard output.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) route_bypass = Attribute("routeBypass", "Sets ping -r option. Bypasses normal routing tables and sends " "ECHO REQUEST packets directly yo a host on an attached interface. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) packetsize = Attribute("packetSize", "Sets ping -s option. Specifies the number of data bytes to be " "sent. Defaults to 56. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) sendbuff = Attribute("sendBuff", "Sets ping -S option. Specifies the number of packets to buffer. " "Defaults to one. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ttl = Attribute("ttl", "Sets ping -t option. Specifies the IP Time to Live for the " "packets. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) timestamp = Attribute("timestamp", "Sets ping -T option. Sets special IP timestamp options. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) hint = Attribute("hint", "Sets ping -M option. Selects Path MTU Discovery strategy. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) full_latency = Attribute("fullLatency", "Sets ping -U option. Calculates round trip time taking into " @@ -129,32 +129,32 @@ class LinuxPing(LinuxApplication): "network round trip time. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) verbose = Attribute("verbose", "Sets ping -v option. Verbose output. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) flood = Attribute("flood", "Sets ping -f option. Flood ping. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) deadline = Attribute("deadline", "Sets ping -w option. Specify a timeout, in seconds, before ping " "exits regardless of how many packets have been sent or received.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) timeout = Attribute("timeout", "Sets ping -W option. Time to wait for a respone in seconds .", - flags = Flags.ExecReadOnly) + flags = Flags.Design) target = Attribute("target", "The host to ping .", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(count) cls._register_attribute(mark) diff --git a/src/nepi/resources/linux/tcpdump.py b/src/nepi/resources/linux/tcpdump.py index 12d11a28..761c03e4 100644 --- a/src/nepi/resources/linux/tcpdump.py +++ b/src/nepi/resources/linux/tcpdump.py @@ -35,25 +35,25 @@ class LinuxTcpdump(LinuxApplication): "Prints each packet (minus its link level header) in ASCII.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) b = Attribute("b", "Sets tcpdump -b option. " "Prints the AS number in BGP packets in ASDOT notation. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) B = Attribute("B", "Sets tcpdump -B option. " "Sets the operaing system capture buffer size in untils of " "KiB (1024 bytes).", - flags = Flags.ExecReadOnly) + flags = Flags.Design) c = Attribute("c", "Sets tcpdump -c option. " "Exists after receiving count packets.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) C = Attribute("C", "Sets tcpdump -C option. " @@ -63,7 +63,7 @@ class LinuxTcpdump(LinuxApplication): "Savefiles after the first savefile will have the name specified " "with the -w with a number after it, starting at 1 and continuing " "upward. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) d = Attribute("d", "Sets tcpdump -d option. " @@ -71,14 +71,14 @@ class LinuxTcpdump(LinuxApplication): "to standard output and stop.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) dd = Attribute("dd", "Sets tcpdump -dd option. " "Dump packet-matching code as a C program fragment. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) ddd = Attribute("ddd", "Sets tcpdump -ddd option. " @@ -86,7 +86,7 @@ class LinuxTcpdump(LinuxApplication): "(preceded with a count).", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) D = Attribute("D", "Sets tcpdump -D option. " @@ -94,19 +94,19 @@ class LinuxTcpdump(LinuxApplication): "and on which tcpdump can capture packets. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) e = Attribute("e", "Sets tcpdump -e option. " "Print the link-level header on each dump line.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) F = Attribute("F", "Sets tcpdump -F option. " "Use file as input for the filter expression.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) G = Attribute("G", "Sets tcpdump -G option. " @@ -114,14 +114,14 @@ class LinuxTcpdump(LinuxApplication): "option every rotate_seconds seconds. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) i = Attribute("i", "Sets tcpdump -i option. " "Listen on interface. If unspecified, tcpdump searches the " "system interface list for the lowest numbered, configured " "up interface (excluding loopback). ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) I = Attribute("I", "Sets tcpdump -I option. " @@ -130,7 +130,7 @@ class LinuxTcpdump(LinuxApplication): "operating systems. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) j = Attribute("j", "Sets tcpdump -j option. " @@ -138,21 +138,21 @@ class LinuxTcpdump(LinuxApplication): "The names to use for the time stamp types are given in " "pcap-tstamp-type(7); not all the types listed there will " "necessarily be valid for any given interface.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) K = Attribute("K", "Sets tcpdump -K option. " "Don't attempt to verify IP, TCP, or UDP checksums. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) l = Attribute("l", "Sets tcpdump -l option. " "Make stdout line buffered. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) U = Attribute("U", "Sets tcpdump -U option. " @@ -161,7 +161,7 @@ class LinuxTcpdump(LinuxApplication): "at the end of each packet. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) n = Attribute("n", "Sets tcpdump -n option. " @@ -169,7 +169,7 @@ class LinuxTcpdump(LinuxApplication): "etc.) to names.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) N = Attribute("N", "Sets tcpdump -N option. " @@ -178,20 +178,20 @@ class LinuxTcpdump(LinuxApplication): "instead of ``nic.ddn.mil''.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) S = Attribute("S", "Sets tcpdump -S option. " "Print absolute, rather than relative, TCP sequence numbers.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) s = Attribute("s", "Sets tcpdump -s option. " "Snarf snaplen bytes of data from each packet rather than " "the default of 65535 bytes. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) T = Attribute("T", "Sets tcpdump -T option. " @@ -203,21 +203,21 @@ class LinuxTcpdump(LinuxApplication): "protocol), snmp (Simple Network Management Protocol), tftp " "(Trivial File Transfer Protocol), vat (Visual Audio Tool), " "and wb (distributed White Board).", - flags = Flags.ExecReadOnly) + flags = Flags.Design) t = Attribute("t", "Sets tcpdump -t option. " "Don't print a timestamp on each dump line.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) tt = Attribute("tt", "Sets tcpdump -tt option. " "Print an unformatted timestamp on each dump line. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) ttt = Attribute("ttt", "Sets tcpdump -ttt option. " @@ -225,7 +225,7 @@ class LinuxTcpdump(LinuxApplication): "and previous line on each dump line.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) tttt = Attribute("tttt", "Sets tcpdump -tttt option. " @@ -233,7 +233,7 @@ class LinuxTcpdump(LinuxApplication): "each dump line. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) ttttt = Attribute("ttttt", "Sets tcpdump -ttttt option. " @@ -241,7 +241,7 @@ class LinuxTcpdump(LinuxApplication): "first line on each dump line.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) v = Attribute("v", "Sets tcpdump -v option. " @@ -249,21 +249,21 @@ class LinuxTcpdump(LinuxApplication): "verbose output. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) vv = Attribute("vv", "Sets tcpdump -vv option. " "Even more verbose output. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) vvv = Attribute("vvv", "Sets tcpdump -vv option. " "Even more verbose output. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) w = Attribute("w", "Sets tcpdump -w option. " @@ -271,11 +271,11 @@ class LinuxTcpdump(LinuxApplication): "and printing them out.", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) expression = Attribute("expression", "selects which packets will be dumped.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(A) cls._register_attribute(b) diff --git a/src/nepi/resources/linux/traceroute.py b/src/nepi/resources/linux/traceroute.py index 99eea6b7..5e592a87 100644 --- a/src/nepi/resources/linux/traceroute.py +++ b/src/nepi/resources/linux/traceroute.py @@ -35,13 +35,13 @@ class LinuxTraceroute(LinuxApplication): "Run traceroute in a while loop", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) print_timestamp = Attribute("printTimestamp", "Print timestamp before running traceroute", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) use_ip = Attribute("useIP", "Use the IP address instead of the host domain name. " @@ -49,11 +49,11 @@ class LinuxTraceroute(LinuxApplication): "frequently", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) target = Attribute("target", "Traceroute target host (host that will be pinged)", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(countinuous) cls._register_attribute(print_timestamp) diff --git a/src/nepi/resources/linux/udptest.py b/src/nepi/resources/linux/udptest.py index 76c59140..46accbc3 100644 --- a/src/nepi/resources/linux/udptest.py +++ b/src/nepi/resources/linux/udptest.py @@ -40,103 +40,103 @@ class LinuxUdpTest(LinuxApplication): "Runs in server mode. ", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) p = Attribute("p", "Port to listen to in server mode, or to connect to in client mode. " "Defaults to 5678. ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) a = Attribute("a", "Client option. Perform UDP Round Trip Time (latency) ", type = Types.Bool, - flags = Flags.ExecReadOnly) + flags = Flags.Design) A = Attribute("A", "Client option. " "Message size for UDP RTT test. " "UDP RTT (latency) test with specified message size.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) b = Attribute("b", "Client option. " "Client UDP buffer size in bytes. Using system default " "value if not defined.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) B = Attribute("B", "Client option. " "Server UDP buffer size in bytes. The same as cleint's by default.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) c = Attribute("c", "Client option. " "CPU log option. Tracing system info during the test. " "Only available when output is defined. ", type = Types.Bool, - flags = Flags.ExecReadOnly) + flags = Flags.Design) d = Attribute("d", "Client option. " "Data size of each read/write in bytes. The same as packet size " "by default.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) e = Attribute("e", "Client option. " "Exponential test (data size of each sending increasing from 1 " "byte to packet size). ", type = Types.Bool, - flags = Flags.ExecReadOnly) + flags = Flags.Design) g = Attribute("g", "Client option. " "UDP traffic generator (Keep sending data to a host). " "Work without server's support.", type = Types.Bool, - flags = Flags.ExecReadOnly) + flags = Flags.Design) target = Attribute("target", "Client option. " "Hostname or IP address of UDP server. Must be specified.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) i = Attribute("i", "Client option. " "Bidirectional UDP throuhgput test. Default is unidirection " "stream test. ", type = Types.Bool, - flags = Flags.ExecReadOnly) + flags = Flags.Design) l = Attribute("l", "Client option. " "UDP datagram (packet) size in bytes ( < udp-buffer-szie ). " "1460 by default.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) m = Attribute("m", "Client option. " "Total message size in bytes. 1048576 by default.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) o = Attribute("o", "Client option. " "Output file name. ", - flags = Flags.ExecReadOnly) + flags = Flags.Design) P = Attribute("P", "Client option. " "Write the plot file for gnuplot. Only enable when the output " "is specified. ", type = Types.Bool, - flags = Flags.ExecReadOnly) + flags = Flags.Design) q = Attribute("q", "Client option. " @@ -152,38 +152,38 @@ class LinuxUdpTest(LinuxApplication): "is specified. ", type = Types.Enumerate, allowed = ["1", "2", "3", "4", "5", "6"], - flags = Flags.ExecReadOnly) + flags = Flags.Design) r = Attribute("r", "Client option. " "Repetition of tests. 10 by default. ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) t = Attribute("t", "Client option. " "Test time constraint in seconds. 5 by default. ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) T = Attribute("T", "Client option. " "Throughput constraint for UDP generator or throughput " "test. Unlimited by default. ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) continuous = Attribute("continuous", "Run nping in a while loop", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) print_timestamp = Attribute("printTimestamp", "Print timestamp before running nping", type = Types.Bool, default = False, - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(s) cls._register_attribute(p) diff --git a/src/nepi/resources/linux/udptunnel.py b/src/nepi/resources/linux/udptunnel.py index 6372729e..44edad61 100644 --- a/src/nepi/resources/linux/udptunnel.py +++ b/src/nepi/resources/linux/udptunnel.py @@ -43,25 +43,25 @@ class UdpTunnel(LinuxApplication): default = None, allowed = ["PLAIN", "AES", "Blowfish", "DES", "DES3"], type = Types.Enumerate, - flags = Flags.ExecReadOnly) + flags = Flags.Design) cipher_key = Attribute("cipherKey", "Specify a symmetric encryption key with which to protect " "packets across the tunnel. python-crypto must be installed " "on the system." , - flags = Flags.ExecReadOnly) + flags = Flags.Design) txqueuelen = Attribute("txQueueLen", "Specifies the interface's transmission queue length. " "Defaults to 1000. ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) bwlimit = Attribute("bwLimit", "Specifies the interface's emulated bandwidth in bytes " "per second.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(cipher) cls._register_attribute(cipher_key) diff --git a/src/nepi/resources/ns3/ns3application.py b/src/nepi/resources/ns3/ns3application.py index f53d5053..6f8ad6bf 100644 --- a/src/nepi/resources/ns3/ns3application.py +++ b/src/nepi/resources/ns3/ns3application.py @@ -30,3 +30,24 @@ class NS3BaseApplication(NS3Base): self.simulator.invoke(node.uuid, "AddApplication", self.uuid) self._connected.add(node.uuid) + def do_start(self): + if self.state == ResourceState.READY: + self.info("Starting") + + # BUG: without doing this explicit call it doesn't start!!! + # Shouldn't be enough to set the StartTime? + self.simulator.invoke(self.uuid, "Start") + + self.set_started() + else: + msg = " Failed " + self.error(msg, out, err) + raise RuntimeError, msg + + def do_stop(self): + if self.state == ResourceState.STARTED: + # No need to do anything, simulator.Destroy() will stop every object + self.info("Stopping command '%s'" % command) + self.simulator.invoke(self.uuid, "Stop") + self.set_stopped() + diff --git a/src/nepi/resources/ns3/ns3base.py b/src/nepi/resources/ns3/ns3base.py index f36ffce2..ba035969 100644 --- a/src/nepi/resources/ns3/ns3base.py +++ b/src/nepi/resources/ns3/ns3base.py @@ -21,15 +21,14 @@ from nepi.execution.resource import ResourceManager, clsinit_copy, \ ResourceState, reschedule_delay from nepi.execution.attribute import Flags -from nepi.resources.ns3.ns3simulator import NS3Simulator @clsinit_copy class NS3Base(ResourceManager): _rtype = "abstract::ns3::Object" _backend_type = "ns3" - def __init__(self): - super(NS3Base, self).__init__() + def __init__(self, ec, guid): + super(NS3Base, self).__init__(ec, guid) self._uuid = None self._connected = set() @@ -43,10 +42,7 @@ class NS3Base(ResourceManager): @property def simulator(self): - simulators = self.get_connected(NS3Simulator.get_rtype()) - if simulators: return simulators[0] - # if the object is not directly connected to the simulator, - # it should be connected to a node + # Ns3 RMs should be connected to the simulator through a ns3 node node = self.node if node: return node.simulator return None @@ -70,13 +66,13 @@ class NS3Base(ResourceManager): return kwargs = dict() - for attr in self._attrs: - if not attr.value or attr.has_flag(Flags.ReadOnly): + for attr in self._attrs.values(): + if not (attr.has_changed() and attr.has_flag(Flags.Construct)): continue kwargs[attr.name] = attr.value - self.uuid = self.simulator.factory(self.get_rtype(), **kwargs) + self._uuid = self.simulator.factory(self.get_rtype(), **kwargs) def _configure_object(self): pass diff --git a/src/nepi/resources/ns3/ns3channel.py b/src/nepi/resources/ns3/ns3channel.py index 063e31b3..7386346b 100644 --- a/src/nepi/resources/ns3/ns3channel.py +++ b/src/nepi/resources/ns3/ns3channel.py @@ -32,6 +32,6 @@ class NS3BaseChannel(NS3Base): @property def simulator(self): devices = self.devices - if devices: return device[0].node.simulator + if devices: return devices[0].node.simulator return None diff --git a/src/nepi/resources/ns3/ns3ipv4l3protocol.py b/src/nepi/resources/ns3/ns3ipv4l3protocol.py index 21554222..67fe21dd 100644 --- a/src/nepi/resources/ns3/ns3ipv4l3protocol.py +++ b/src/nepi/resources/ns3/ns3ipv4l3protocol.py @@ -25,9 +25,11 @@ class NS3BaseIpv4L3Protocol(NS3Base): _rtype = "abstract::ns3::Ipv4L3Protocol" def _configure_object(self): + simulator = self.simulator + uuid_list_routing = simulator.create("Ipv4ListRouting") simulator.invoke(self.uuid, "SetRoutingProtocol", uuid_list_routing) uuid_static_routing = simulator.create("Ipv4StaticRouting") - simulator.invoke(self.uuid, "SetRoutingProtocol", uuid_static_routing, 1) + simulator.invoke(uuid_list_routing, "AddRoutingProtocol", uuid_static_routing, 1) diff --git a/src/nepi/resources/ns3/ns3netdevice.py b/src/nepi/resources/ns3/ns3netdevice.py index 4978c7e0..009d14cf 100644 --- a/src/nepi/resources/ns3/ns3netdevice.py +++ b/src/nepi/resources/ns3/ns3netdevice.py @@ -21,6 +21,8 @@ from nepi.execution.attribute import Attribute, Flags from nepi.execution.resource import clsinit_copy from nepi.resources.ns3.ns3base import NS3Base +import ipaddr + @clsinit_copy class NS3BaseNetDevice(NS3Base): _rtype = "abstract::ns3::NetDevice" @@ -28,13 +30,13 @@ class NS3BaseNetDevice(NS3Base): @classmethod def _register_attributes(cls): mac = Attribute("mac", "MAC address for device", - flags = Flags.ExecReadOnly) + flags = Flags.Design) ip = Attribute("ip", "IP address for device", - flags = Flags.ExecReadOnly) + flags = Flags.Design) prefix = Attribute("prefix", "Network prefix for device", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(mac) cls._register_attribute(ip) @@ -42,7 +44,7 @@ class NS3BaseNetDevice(NS3Base): @property def channel(self): - from nepi.resources.ns3.ns3channel import NS3Channel + from nepi.resources.ns3.ns3channel import NS3BaseChannel channels = self.get_connected(NS3BaseChannel.get_rtype()) if channels: return channels[0] return None diff --git a/src/nepi/resources/ns3/ns3node.py b/src/nepi/resources/ns3/ns3node.py index 7d0380ca..0cecfa7c 100644 --- a/src/nepi/resources/ns3/ns3node.py +++ b/src/nepi/resources/ns3/ns3node.py @@ -19,11 +19,21 @@ from nepi.execution.resource import clsinit_copy from nepi.resources.ns3.ns3base import NS3Base +from nepi.resources.ns3.ns3simulator import NS3Simulator @clsinit_copy class NS3BaseNode(NS3Base): _rtype = "abstract::ns3::Node" + @property + def simulator(self): + for guid in self.connections: + rm = self.ec.get_resource(guid) + if isinstance(rm, NS3Simulator): + return rm + + return None + @property def ipv4(self): from nepi.resources.ns3.ns3ipv4l3protocol import NS3BaseIpv4L3Protocol diff --git a/src/nepi/resources/ns3/ns3queue.py b/src/nepi/resources/ns3/ns3queue.py index 55ed57f4..a02a96e8 100644 --- a/src/nepi/resources/ns3/ns3queue.py +++ b/src/nepi/resources/ns3/ns3queue.py @@ -26,7 +26,7 @@ class NS3BaseQueue(NS3Base): @property def device(self): - from nepi.resources.ns3.ns3device import NS3BaseNetDevice + from nepi.resources.ns3.ns3netdevice import NS3BaseNetDevice devices = self.get_connected(NS3BaseNetDevice.get_rtype()) if devices: return devices[0] return None diff --git a/src/nepi/resources/ns3/ns3server.py b/src/nepi/resources/ns3/ns3server.py index b6df768a..9e3920f4 100644 --- a/src/nepi/resources/ns3/ns3server.py +++ b/src/nepi/resources/ns3/ns3server.py @@ -20,7 +20,10 @@ import base64 import cPickle import errno +import logging +import os import socket + from optparse import OptionParser, SUPPRESS_HELP from ns3wrapper import NS3Wrapper @@ -39,6 +42,9 @@ class NS3WrapperMessage: def handle_message(ns3_wrapper, msg, args): if msg == NS3WrapperMessage.SHUTDOWN: ns3_wrapper.shutdown() + + ns3_wrapper.logger.debug("SHUTDOWN") + return "BYEBYE" if msg == NS3WrapperMessage.STOP: @@ -46,16 +52,22 @@ def handle_message(ns3_wrapper, msg, args): if args: time = args[0] + ns3_wrapper.logger.debug("STOP time=%s" % str(time)) + ns3_wrapper.stop(time=time) return "STOPPED" if msg == NS3WrapperMessage.START: + ns3_wrapper.logger.debug("START") + ns3_wrapper.start() return "STARTED" if msg == NS3WrapperMessage.CREATE: clazzname = args.pop(0) + ns3_wrapper.logger.debug("CREATE %s %s" % (clazzname, str(args))) + uuid = ns3_wrapper.create(clazzname, *args) return uuid @@ -63,6 +75,8 @@ def handle_message(ns3_wrapper, msg, args): type_name = args.pop(0) kwargs = args.pop(0) + ns3_wrapper.logger.debug("FACTORY %s %s" % (type_name, str(kwargs))) + uuid = ns3_wrapper.factory(type_name, **kwargs) return uuid @@ -70,6 +84,8 @@ def handle_message(ns3_wrapper, msg, args): uuid = args.pop(0) operation = args.pop(0) + ns3_wrapper.logger.debug("INVOKE %s %s %s" % (uuid, operation, str(args))) + uuid = ns3_wrapper.invoke(uuid, operation, *args) return uuid @@ -77,6 +93,8 @@ def handle_message(ns3_wrapper, msg, args): uuid = args.pop(0) name = args.pop(0) + ns3_wrapper.logger.debug("GET %s %s" % (uuid, name)) + value = ns3_wrapper.get(uuid, name) return value @@ -85,10 +103,13 @@ def handle_message(ns3_wrapper, msg, args): name = args.pop(0) value = args.pop(0) + ns3_wrapper.logger.debug("SET %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" def create_socket(socket_name): @@ -135,7 +156,7 @@ def send_reply(conn, reply): conn.send("%s\n" % encoded) def get_options(): - usage = ("usage: %prog -S ") + usage = ("usage: %prog -S -L -v ") parser = OptionParser(usage = usage) @@ -143,12 +164,30 @@ def get_options(): help = "Name for the unix socket used to interact with this process", default = "tap.sock", type="str") + parser.add_option("-L", "--ns-log", dest="ns_log", + help = "NS_LOG environmental variable to be set", + default = "", type="str") + + parser.add_option("-v", "--verbose", + help="Print debug output", + action="store_true", + dest="verbose", default=False) + (options, args) = parser.parse_args() - return options.socket_name + return options.socket_name, options.verbose, options.ns_log + +def run_server(socket_name, verbose = False, ns_log = None): -def run_server(socket_name): - ns3_wrapper = NS3Wrapper() + level = logging.DEBUG if verbose else logging.INFO + + # Sets NS_LOG environmental variable for NS debugging + if ns_log: + os.environ["NS_LOG"] = ns_log + + ###### ns-3 wrapper instantiation + + ns3_wrapper = NS3Wrapper(loglevel=level) # create unix socket to receive instructions sock = create_socket(socket_name) @@ -170,8 +209,6 @@ def run_server(socket_name): if not msg: # Ignore - connection lost break - - ns3_wrapper.logger.debug("Message received %s args %s" % ( msg, str(args))) if msg == NS3WrapperMessage.SHUTDOWN: stop = True @@ -185,7 +222,7 @@ def run_server(socket_name): if __name__ == '__main__': - socket_name = get_options() + (socket_name, verbose, ns_log) = get_options() - run_server(socket_name) + run_server(socket_name, verbose, ns_log) diff --git a/src/nepi/resources/ns3/ns3wrapper.py b/src/nepi/resources/ns3/ns3wrapper.py index 064b32ce..47525f96 100644 --- a/src/nepi/resources/ns3/ns3wrapper.py +++ b/src/nepi/resources/ns3/ns3wrapper.py @@ -86,7 +86,7 @@ def load_ns3_module(): return ns3mod class NS3Wrapper(object): - def __init__(self, homedir = None): + def __init__(self, homedir = None, loglevel = logging.INFO): super(NS3Wrapper, self).__init__() # Thread used to run the simulation self._simulation_thread = None @@ -107,9 +107,8 @@ class NS3Wrapper(object): os.makedirs(home, 0755) # Logging - loglevel = os.environ.get("NS3LOGLEVEL", "debug") self._logger = logging.getLogger("ns3wrapper") - self._logger.setLevel(getattr(logging, loglevel.upper())) + self._logger.setLevel(loglevel) hdlr = logging.FileHandler(os.path.join(self.homedir, "ns3wrapper.log")) formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') @@ -180,7 +179,7 @@ class NS3Wrapper(object): return self._objects.get(uuid) def factory(self, type_name, **kwargs): - if type_name not in allowed_types: + if type_name not in self.allowed_types: msg = "Type %s not supported" % (type_name) self.logger.error(msg) diff --git a/src/nepi/resources/ns3/resource_manager_generator.py b/src/nepi/resources/ns3/resource_manager_generator.py index fd5e7003..5cb7cc18 100644 --- a/src/nepi/resources/ns3/resource_manager_generator.py +++ b/src/nepi/resources/ns3/resource_manager_generator.py @@ -159,7 +159,9 @@ def template_attributes(ns3, tid): attr_flags = "None" flags = attr_info.flags if (flags & ns3.TypeId.ATTR_SET) != ns3.TypeId.ATTR_SET: - attr_flags = "Flags.ExecReadOnly" + attr_flags = "Flags.Design" + elif (flags & ns3.TypeId.ATTR_CONSTRUCT) == ns3.TypeId.ATTR_CONSTRUCT: + attr_flags = "Flags.Construct" attr_name = attr_info.name checker = attr_info.checker diff --git a/src/nepi/resources/omf/application.py b/src/nepi/resources/omf/application.py index bc4d0e77..8ef2b509 100644 --- a/src/nepi/resources/omf/application.py +++ b/src/nepi/resources/omf/application.py @@ -52,11 +52,11 @@ class OMFApplication(OMFResource): env = Attribute("env", "Environnement variable of the application") stdin = Attribute("stdin", "Input of the application", default = "") sources = Attribute("sources", "Sources of the application", - flags = Flags.ExecReadOnly) + flags = Flags.Design) sshuser = Attribute("sshUser", "user to connect with ssh", - flags = Flags.ExecReadOnly) + flags = Flags.Design) sshkey = Attribute("sshKey", "key to use for ssh", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(appid) cls._register_attribute(path) cls._register_attribute(args) diff --git a/src/nepi/resources/planetlab/node.py b/src/nepi/resources/planetlab/node.py index 9ce3e3bb..7782bd80 100644 --- a/src/nepi/resources/planetlab/node.py +++ b/src/nepi/resources/planetlab/node.py @@ -44,7 +44,7 @@ class PlanetlabNode(LinuxNode): @classmethod def _register_attributes(cls): ip = Attribute("ip", "PlanetLab host public IP address", - flags = Flags.ReadOnly) + flags = Flags.Design) pl_url = Attribute("plcApiUrl", "URL of PlanetLab PLCAPI host \ (e.g. www.planet-lab.eu or www.planet-lab.org) ", @@ -54,7 +54,7 @@ class PlanetlabNode(LinuxNode): pl_ptn = Attribute("plcApiPattern", "PLC API service regexp pattern \ (e.g. https://%(hostname)s:443/PLCAPI/ ) ", default = "https://%(hostname)s:443/PLCAPI/", - flags = Flags.ExecReadOnly) + flags = Flags.Design) pl_user = Attribute("pluser", "PlanetLab account user, as the one to \ authenticate in the website) ", diff --git a/src/nepi/resources/planetlab/openvswitch/ovs.py b/src/nepi/resources/planetlab/openvswitch/ovs.py index b3ce59d8..f4b50c6c 100644 --- a/src/nepi/resources/planetlab/openvswitch/ovs.py +++ b/src/nepi/resources/planetlab/openvswitch/ovs.py @@ -43,13 +43,13 @@ class OVSWitch(LinuxApplication): """ bridge_name = Attribute("bridge_name", "Name of the switch/bridge", - flags = Flags.ExecReadOnly) + flags = Flags.Design) virtual_ip_pref = Attribute("virtual_ip_pref", "Virtual IP/PREFIX of the switch", - flags = Flags.ExecReadOnly) + flags = Flags.Design) controller_ip = Attribute("controller_ip", "IP of the controller", - flags = Flags.ExecReadOnly) + flags = Flags.Design) controller_port = Attribute("controller_port", "Port of the controller", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(bridge_name) cls._register_attribute(virtual_ip_pref) diff --git a/src/nepi/resources/planetlab/openvswitch/ovsport.py b/src/nepi/resources/planetlab/openvswitch/ovsport.py index 57b6f16c..cd2e848d 100644 --- a/src/nepi/resources/planetlab/openvswitch/ovsport.py +++ b/src/nepi/resources/planetlab/openvswitch/ovsport.py @@ -51,7 +51,7 @@ class OVSPort(LinuxApplication): """ port_name = Attribute("port_name", "Name of the port", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(port_name) diff --git a/src/nepi/resources/planetlab/openvswitch/tunnel.py b/src/nepi/resources/planetlab/openvswitch/tunnel.py index a494212e..359682cf 100644 --- a/src/nepi/resources/planetlab/openvswitch/tunnel.py +++ b/src/nepi/resources/planetlab/openvswitch/tunnel.py @@ -60,25 +60,25 @@ class OVSTunnel(LinuxApplication): default = None, allowed = ["PLAIN", "AES", "Blowfish", "DES", "DES3"], type = Types.Enumerate, - flags = Flags.ExecReadOnly) + flags = Flags.Design) cipher_key = Attribute("cipherKey", "Specify a symmetric encryption key with which to protect " "packets across the tunnel. python-crypto must be installed " "on the system." , - flags = Flags.ExecReadOnly) + flags = Flags.Design) txqueuelen = Attribute("txQueueLen", "Specifies the interface's transmission queue length. " "Defaults to 1000. ", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) bwlimit = Attribute("bwLimit", "Specifies the interface's emulated bandwidth in bytes " "per second.", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(cipher) cls._register_attribute(cipher_key) diff --git a/src/nepi/resources/planetlab/tap.py b/src/nepi/resources/planetlab/tap.py index 5ca85905..6cc490ac 100644 --- a/src/nepi/resources/planetlab/tap.py +++ b/src/nepi/resources/planetlab/tap.py @@ -42,35 +42,35 @@ class PlanetlabTap(LinuxApplication): @classmethod def _register_attributes(cls): ip4 = Attribute("ip4", "IPv4 Address", - flags = Flags.ExecReadOnly) + flags = Flags.Design) mac = Attribute("mac", "MAC Address", - flags = Flags.ExecReadOnly) + flags = Flags.Design) prefix4 = Attribute("prefix4", "IPv4 network prefix", type = Types.Integer, - flags = Flags.ExecReadOnly) + flags = Flags.Design) mtu = Attribute("mtu", "Maximum transmition unit for device", type = Types.Integer) devname = Attribute("deviceName", "Name of the network interface (e.g. eth0, wlan0, etc)", - flags = Flags.ReadOnly) + flags = Flags.NoWrite) up = Attribute("up", "Link up", type = Types.Bool) snat = Attribute("snat", "Set SNAT=1", type = Types.Bool, - flags = Flags.ExecReadOnly) + flags = Flags.Design) pointopoint = Attribute("pointopoint", "Peer IP address", - flags = Flags.ExecReadOnly) + flags = Flags.Design) tear_down = Attribute("tearDown", "Bash script to be executed before " + \ "releasing the resource", - flags = Flags.ExecReadOnly) + flags = Flags.Design) cls._register_attribute(ip4) cls._register_attribute(mac) diff --git a/src/nepi/util/execfuncs.py b/src/nepi/util/execfuncs.py index e09d4905..cd11bfae 100644 --- a/src/nepi/util/execfuncs.py +++ b/src/nepi/util/execfuncs.py @@ -41,13 +41,13 @@ def lexec(command, command = "su %s ; %s " % (user, command) - p = subprocess.Popen(command, shell=True, + proc = subprocess.Popen(command, shell=True, stdout = subprocess.PIPE, stderr = subprocess.PIPE) #stdin = stdin) - out, err = p.communicate() - return (out, err) + out, err = proc.communicate() + return ((out, err), proc) def lcopy(source, dest, recursive = False): """ @@ -64,7 +64,7 @@ def lcopy(source, dest, recursive = False): command.append(src) command.append(dst) - p = subprocess.Popen(command, + proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -128,12 +128,12 @@ def lspawn(command, pidfile, 'create' : 'mkdir -p %s ; ' % (shell_escape(home),) if create_home else '', } - (out,err),proc = lexec(cmd) + (out,err), proc = lexec(cmd) if proc.wait(): raise RuntimeError, "Failed to set up application on host %s: %s %s" % (host, out,err,) - return (out,err),proc + return ((out,err), proc) def lgetpid(pidfile): """ @@ -148,7 +148,7 @@ def lgetpid(pidfile): or None if the pidfile isn't valid yet (maybe the process is still starting). """ - (out,err),proc = lexec("cat %s" % pidfile ) + (out,err), proc = lexec("cat %s" % pidfile ) if proc.wait(): return None @@ -172,7 +172,7 @@ def lstatus(pid, ppid): One of NOT_STARTED, RUNNING, FINISHED """ - (out,err),proc = lexec( + (out,err), proc = lexec( # Check only by pid. pid+ppid does not always work (especially with sudo) " (( ps --pid %(pid)d -o pid | grep -c %(pid)d && echo 'wait') || echo 'done' ) | tail -n 1" % { 'ppid' : ppid, @@ -187,8 +187,8 @@ def lstatus(pid, ppid): status = (out.strip() == 'wait') else: return ProcStatus.NOT_STARTED + return ProcStatus.RUNNING if status else ProcStatus.FINISHED - def lkill(pid, ppid, sudo = False): """ diff --git a/test/resources/linux/ns3/ns3client.py b/test/resources/linux/ns3/ns3client.py index 404fc5d2..aea015b0 100644 --- a/test/resources/linux/ns3/ns3client.py +++ b/test/resources/linux/ns3/ns3client.py @@ -41,6 +41,8 @@ import unittest class LinuxNS3ClientTest(unittest.TestCase): def setUp(self): self.socket_name = os.path.join("/", "tmp", "NS3WrapperServer.sock") + if os.path.exists(self.socket_name): + os.remove(self.socket_name) def tearDown(self): os.remove(self.socket_name) diff --git a/test/resources/linux/ns3/ns3simulator.py b/test/resources/linux/ns3/ns3simulator.py new file mode 100644 index 00000000..9f17072c --- /dev/null +++ b/test/resources/linux/ns3/ns3simulator.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2013 INRIA +# +# This program 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. +# +# This program 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 . +# +# Author: Alina Quereilhac + + +# +# Network topology +# +# n0 n1 n2 n3 +# | | | | +# ----------------- +# +# node n0 sends IGMP traffic to node n3 + + +from nepi.execution.ec import ExperimentController +from nepi.resources.ns3.ns3server import run_server + +import os +import threading +import time +import unittest + +class LinuxNS3ClientTest(unittest.TestCase): + def setUp(self): + self.socket_name = os.path.join("/", "tmp", "NS3WrapperServerSimu.sock") + if os.path.exists(self.socket_name): + os.remove(self.socket_name) + + def tearDown(self): + os.remove(self.socket_name) + + def test_runtime_attr_modify(self): + thread = threading.Thread(target = run_server, + args = [self.socket_name], + kwargs = {"verbose" : True, + "ns_log": "V4Ping:Node"}) + + thread.setDaemon(True) + thread.start() + + time.sleep(1) + + ec = ExperimentController(exp_id = "test-ns3-simu") + + node = ec.register_resource("LinuxNode") + ec.set(node, "hostname", "localhost") + + simu = ec.register_resource("LinuxNS3Simulator") + ec.set(simu, "socketName", self.socket_name) + ec.register_connection(simu, node) + + nsnode1 = ec.register_resource("ns3::Node") + ec.register_connection(nsnode1, simu) + + ipv41 = ec.register_resource("ns3::Ipv4L3Protocol") + ec.register_connection(nsnode1, ipv41) + + arp1 = ec.register_resource("ns3::ArpL3Protocol") + ec.register_connection(nsnode1, arp1) + + icmp1 = ec.register_resource("ns3::Icmpv4L4Protocol") + ec.register_connection(nsnode1, icmp1) + + p1 = ec.register_resource("ns3::PointToPointNetDevice") + ec.set(p1, "ip", "10.0.0.1") + ec.set(p1, "prefix", "30") + ec.register_connection(nsnode1, p1) + q1 = ec.register_resource("ns3::DropTailQueue") + ec.register_connection(nsnode1, q1) + + nsnode2 = ec.register_resource("ns3::Node") + ec.register_connection(nsnode2, simu) + + ipv42 = ec.register_resource("ns3::Ipv4L3Protocol") + ec.register_connection(nsnode2, ipv42) + + arp2 = ec.register_resource("ns3::ArpL3Protocol") + ec.register_connection(nsnode2, arp2) + + icmp2 = ec.register_resource("ns3::Icmpv4L4Protocol") + ec.register_connection(nsnode2, icmp2) + + p2 = ec.register_resource("ns3::PointToPointNetDevice") + ec.set(p2, "ip", "10.0.0.2") + ec.set(p2, "prefix", "30") + ec.register_connection(nsnode2, p2) + q2 = ec.register_resource("ns3::DropTailQueue") + ec.register_connection(nsnode2, q2) + + # Create channel + chan = ec.register_resource("ns3::PointToPointChannel") + ec.set(chan, "Delay", "0s") + ec.register_connection(chan, p1) + ec.register_connection(chan, p2) + + ### create pinger + ping = ec.register_resource("ns3::V4Ping") + ec.set (ping, "Remote", "10.0.0.2") + ec.set (ping, "Interval", "1s") + ec.set (ping, "Verbose", True) + ec.set (ping, "StartTime", "0s") + ec.set (ping, "StopTime", "20s") + ec.register_connection(ping, nsnode1) + + ec.deploy() + + time.sleep(5) + + ec.shutdown() + + +if __name__ == '__main__': + unittest.main() + -- 2.47.0