refactored configuration managers and options into a single class, now the models that can be configured will deal with and handle configurations for nodes themselves
This commit is contained in:
parent
1b843e2868
commit
52230bc026
22 changed files with 284 additions and 422 deletions
|
@ -94,80 +94,55 @@ class ConfigurableOptions(object):
|
|||
# unique name to receive configuration changes
|
||||
name = None
|
||||
bitmap = None
|
||||
configuration_maps = None
|
||||
_default_node = -1
|
||||
|
||||
@classmethod
|
||||
def configurations(cls):
|
||||
"""
|
||||
Returns configuration options supported by this class.
|
||||
|
||||
:return: list of configuration options
|
||||
:rtype: list[Configuration]
|
||||
"""
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def config_groups(cls):
|
||||
"""
|
||||
String formatted to specify configuration groupings, using list index positions.
|
||||
|
||||
Example:
|
||||
"Group1:start-stop|Group2:start-stop"
|
||||
|
||||
:return: config groups
|
||||
:rtype: str
|
||||
"""
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def default_values(cls):
|
||||
"""
|
||||
Retrieves default values for configurations.
|
||||
|
||||
:return: mapping of configuration options that can also be iterated in order of definition
|
||||
:rtype: OrderedDict
|
||||
"""
|
||||
return OrderedDict([(config.id, config.default) for config in cls.configurations()])
|
||||
|
||||
@classmethod
|
||||
def nodes(cls):
|
||||
return {node_id for node_id in cls.configuration_maps.iterkeys() if node_id != cls._default_node}
|
||||
|
||||
class ConfigurableManager(object):
|
||||
_default_node = -1
|
||||
_default_type = "default"
|
||||
|
||||
def __init__(self):
|
||||
self._configuration_maps = {}
|
||||
|
||||
def nodes(self):
|
||||
return [node_id for node_id in self._configuration_maps.iterkeys() if node_id != self._default_node]
|
||||
|
||||
def config_reset(self, node_id=None):
|
||||
logger.debug("resetting all configurations: %s", self.__class__.__name__)
|
||||
@classmethod
|
||||
def config_reset(cls, node_id=None):
|
||||
if not node_id:
|
||||
self._configuration_maps.clear()
|
||||
elif node_id in self._configuration_maps:
|
||||
self._configuration_maps.pop(node_id)
|
||||
logger.debug("resetting all configurations: %s", cls.__name__)
|
||||
cls.configuration_maps.clear()
|
||||
elif node_id in cls.configuration_maps:
|
||||
logger.debug("resetting node(%s) configurations: %s", node_id, cls.__name__)
|
||||
cls.configuration_maps.pop(node_id)
|
||||
|
||||
def set_config(self, _id, value, node_id=_default_node, config_type=_default_type):
|
||||
logger.debug("setting config for node(%s) type(%s): %s=%s", node_id, config_type, _id, value)
|
||||
node_type_map = self.get_configs(node_id, config_type)
|
||||
node_type_map[_id] = value
|
||||
@classmethod
|
||||
def set_config(cls, _id, value, node_id=_default_node):
|
||||
logger.debug("setting config for node(%s) type(%s): %s=%s", node_id, _id, value)
|
||||
node_configs = cls.get_configs(node_id)
|
||||
node_configs[_id] = value
|
||||
|
||||
def set_configs(self, config, node_id=_default_node, config_type=_default_type):
|
||||
logger.debug("setting config for node(%s) type(%s): %s", node_id, config_type, config)
|
||||
node_configs = self.get_all_configs(node_id)
|
||||
if config_type in node_configs:
|
||||
node_configs.pop(config_type)
|
||||
node_configs[config_type] = config
|
||||
@classmethod
|
||||
def get_config(cls, _id, node_id=_default_node):
|
||||
logger.debug("getting config for node(%s): %s", node_id, _id)
|
||||
node_configs = cls.get_configs(node_id)
|
||||
return node_configs.get(_id)
|
||||
|
||||
def get_config(self, _id, node_id=_default_node, config_type=_default_type):
|
||||
logger.debug("getting config for node(%s) type(%s): %s", node_id, config_type, _id)
|
||||
node_type_map = self.get_configs(node_id, config_type)
|
||||
return node_type_map.get(_id)
|
||||
@classmethod
|
||||
def set_configs(cls, config=None, node_id=_default_node):
|
||||
logger.debug("setting config for node(%s): %s", node_id, config)
|
||||
node_config = cls.get_configs(node_id)
|
||||
if config:
|
||||
for key, value in config.iteritems():
|
||||
node_config[key] = value
|
||||
|
||||
def get_configs(self, node_id=_default_node, config_type=_default_type):
|
||||
logger.debug("getting configs for node(%s) type(%s)", node_id, config_type)
|
||||
node_map = self.get_all_configs(node_id)
|
||||
return node_map.setdefault(config_type, {})
|
||||
|
||||
def get_all_configs(self, node_id=_default_node):
|
||||
logger.debug("getting all configs for node(%s)", node_id)
|
||||
return self._configuration_maps.setdefault(node_id, OrderedDict())
|
||||
@classmethod
|
||||
def get_configs(cls, node_id=_default_node):
|
||||
logger.debug("getting configs for node(%s)", node_id)
|
||||
return cls.configuration_maps.setdefault(node_id, cls.default_values())
|
||||
|
|
|
@ -955,7 +955,6 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
|||
node_id = config_data.node
|
||||
self.session.location.reset()
|
||||
self.session.services.reset()
|
||||
self.session.mobility.reset()
|
||||
self.session.mobility.config_reset(node_id)
|
||||
self.session.emane.config_reset(node_id)
|
||||
else:
|
||||
|
@ -1139,7 +1138,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
|||
logger.error(error_message)
|
||||
else:
|
||||
if opaque is None:
|
||||
values = values.split('|')
|
||||
values = values.split("|")
|
||||
# store default services for a node type in self.defaultservices[]
|
||||
if data_types is None or data_types[0] != ConfigDataTypes.STRING.value:
|
||||
logger.info(error_message)
|
||||
|
@ -1151,7 +1150,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
|||
# store service customized config in self.customservices[]
|
||||
services, unknown = self.session.services.servicesfromopaque(opaque, node_id)
|
||||
for u in unknown:
|
||||
logger.warn("Request for unknown service '%s'" % u)
|
||||
logger.warn("request for unknown service: %s", u)
|
||||
|
||||
if services:
|
||||
svc = services[0]
|
||||
|
@ -1187,10 +1186,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
|||
logger.warn("model class does not exist: %s", object_name)
|
||||
return []
|
||||
|
||||
config = self.session.mobility.get_configs(node_id, object_name)
|
||||
if not config:
|
||||
config = model_class.default_values()
|
||||
|
||||
config = model_class.get_configs(node_id=node_id)
|
||||
config_response = ConfigShim.config_data(0, node_id, typeflags, model_class, config)
|
||||
replies.append(config_response)
|
||||
elif message_type == ConfigFlags.RESET:
|
||||
|
@ -1207,15 +1203,12 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
|||
logger.warn("model class does not exist: %s", object_name)
|
||||
return []
|
||||
|
||||
config = model_class.default_values()
|
||||
if values_str:
|
||||
parsed_config = ConfigShim.str_to_dict(values_str)
|
||||
for name, value in parsed_config.iteritems():
|
||||
config[name] = value
|
||||
else:
|
||||
config = self.session.mobility.get_configs(node_id, object_name) or config
|
||||
model_class.set_configs(parsed_config, node_id=node_id)
|
||||
|
||||
self.session.mobility.set_configs(config, node_id, object_name)
|
||||
config = model_class.get_configs(node_id)
|
||||
model_class.set_configs(config, node_id=node_id)
|
||||
|
||||
return replies
|
||||
|
||||
|
@ -1282,10 +1275,7 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
|||
logger.warn("model class does not exist: %s", object_name)
|
||||
return []
|
||||
|
||||
config = self.session.emane.get_configs(node_id, object_name)
|
||||
if not config:
|
||||
config = model_class.default_values()
|
||||
|
||||
config = model_class.get_configs(node_id=node_id)
|
||||
config_response = ConfigShim.config_data(0, node_id, typeflags, model_class, config)
|
||||
replies.append(config_response)
|
||||
elif message_type == ConfigFlags.RESET:
|
||||
|
@ -1302,15 +1292,13 @@ class CoreHandler(SocketServer.BaseRequestHandler):
|
|||
logger.warn("model class does not exist: %s", object_name)
|
||||
return []
|
||||
|
||||
config = model_class.default_values()
|
||||
if values_str:
|
||||
parsed_config = ConfigShim.str_to_dict(values_str)
|
||||
for name, value in parsed_config.iteritems():
|
||||
config[name] = value
|
||||
else:
|
||||
config = self.session.emane.get_configs(node_id, object_name) or config
|
||||
model_class.set_configs(parsed_config, node_id=node_id)
|
||||
|
||||
self.session.emane.set_configs(config, node_id, object_name)
|
||||
config = model_class.get_configs(node_id)
|
||||
model_class.set_configs(config, node_id=node_id)
|
||||
self.session.emane.set_node_model(node_id, object_name)
|
||||
|
||||
return replies
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ from core.enumerations import ConfigDataTypes
|
|||
|
||||
class EmaneBypassModel(emanemodel.EmaneModel):
|
||||
name = "emane_bypass"
|
||||
configuration_maps = {}
|
||||
|
||||
# values to ignore, when writing xml files
|
||||
config_ignore = {"none"}
|
||||
|
|
|
@ -29,6 +29,7 @@ def convert_none(x):
|
|||
|
||||
class EmaneCommEffectModel(emanemodel.EmaneModel):
|
||||
name = "emane_commeffect"
|
||||
configuration_maps = {}
|
||||
|
||||
shim_library = "commeffectshim"
|
||||
shim_xml = "/usr/share/emane/manifest/commeffectshim.xml"
|
||||
|
@ -54,8 +55,7 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
|
|||
:param interface: interface for the emane node
|
||||
:return: nothing
|
||||
"""
|
||||
default_values = self.default_values()
|
||||
config = emane_manager.getifcconfig(self.object_id, self.name, default_values, interface)
|
||||
config = self.getifcconfig(self.object_id, interface)
|
||||
if not config:
|
||||
return
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ from core import logger
|
|||
from core.api import coreapi
|
||||
from core.api import dataconversion
|
||||
from core.conf import ConfigShim
|
||||
from core.conf import ConfigurableManager
|
||||
from core.conf import Configuration
|
||||
from core.emane import emanemanifest
|
||||
from core.emane.bypass import EmaneBypassModel
|
||||
|
@ -54,7 +53,7 @@ EMANE_MODELS = [
|
|||
]
|
||||
|
||||
|
||||
class EmaneManager(ConfigurableManager):
|
||||
class EmaneManager(object):
|
||||
"""
|
||||
EMANE controller object. Lives in a Session instance and is used for
|
||||
building EMANE config files from all of the EmaneNode objects in this
|
||||
|
@ -74,7 +73,6 @@ class EmaneManager(ConfigurableManager):
|
|||
:param core.session.Session session: session this manager is tied to
|
||||
:return: nothing
|
||||
"""
|
||||
super(EmaneManager, self).__init__()
|
||||
self.session = session
|
||||
self._emane_nodes = {}
|
||||
self._emane_node_lock = threading.Lock()
|
||||
|
@ -87,8 +85,10 @@ class EmaneManager(ConfigurableManager):
|
|||
self.eventmonthread = None
|
||||
|
||||
# model for global EMANE configuration options
|
||||
self.emane_config = EmaneGlobalModel(session, None)
|
||||
self.set_configs(self.emane_config.default_values())
|
||||
self.emane_config = EmaneGlobalModel(session)
|
||||
|
||||
# store the last configured model for a node, used during startup
|
||||
self.node_models = {}
|
||||
|
||||
session.broker.handlers.add(self.handledistributed)
|
||||
self.service = None
|
||||
|
@ -98,9 +98,19 @@ class EmaneManager(ConfigurableManager):
|
|||
self.service = None
|
||||
self.emane_check()
|
||||
|
||||
def set_node_model(self, node_id, model_name):
|
||||
if model_name not in self._modelclsmap:
|
||||
raise ValueError("unknown emane model: %s", model_name)
|
||||
self.node_models[node_id] = model_name
|
||||
|
||||
def config_reset(self, node_id=None):
|
||||
super(EmaneManager, self).config_reset(node_id)
|
||||
self.set_configs(self.emane_config.default_values())
|
||||
# clear and reset current emane configuration
|
||||
self.emane_config.config_reset()
|
||||
self.emane_config.set_configs()
|
||||
|
||||
# reset model configurations
|
||||
for model_class in self._modelclsmap.itervalues():
|
||||
model_class.config_reset(node_id=node_id)
|
||||
|
||||
def emane_models(self):
|
||||
return self._modelclsmap.keys()
|
||||
|
@ -152,8 +162,8 @@ class EmaneManager(ConfigurableManager):
|
|||
return
|
||||
|
||||
# Get the control network to be used for events
|
||||
group, port = self.get_config("eventservicegroup").split(":")
|
||||
self.event_device = self.get_config("eventservicedevice")
|
||||
group, port = self.emane_config.get_config("eventservicegroup").split(":")
|
||||
self.event_device = self.emane_config.get_config("eventservicedevice")
|
||||
eventnetidx = self.session.get_control_net_index(self.event_device)
|
||||
if eventnetidx < 0:
|
||||
logger.error("invalid emane event service device provided: %s", self.event_device)
|
||||
|
@ -212,54 +222,14 @@ class EmaneManager(ConfigurableManager):
|
|||
"""
|
||||
Used with XML export.
|
||||
"""
|
||||
configs = self.get_all_configs(node.objid)
|
||||
models = []
|
||||
for model_name, config in configs.iteritems():
|
||||
model_class = self._modelclsmap[model_name]
|
||||
models.append((model_class, config))
|
||||
for model_class in self._modelclsmap.itervalues():
|
||||
if node.objid in model_class.configuration_maps:
|
||||
config = model_class.get_configs(node_id=node.objid)
|
||||
models.append((model_class, config))
|
||||
logger.debug("emane models: %s", models)
|
||||
return models
|
||||
|
||||
def getifcconfig(self, node_id, config_type, default_values, ifc):
|
||||
"""
|
||||
Retrieve interface configuration or node configuration if not provided.
|
||||
|
||||
:param int node_id: node id
|
||||
:param str config_type: configuration type
|
||||
:param dict default_values: default configuration values
|
||||
:param ifc: node interface
|
||||
:return:
|
||||
"""
|
||||
# use the network-wide config values or interface(NEM)-specific values?
|
||||
if ifc is None:
|
||||
return self.get_configs(node_id, config_type) or default_values
|
||||
else:
|
||||
# don"t use default values when interface config is the same as net
|
||||
# note here that using ifc.node.objid as key allows for only one type
|
||||
# of each model per node;
|
||||
# TODO: use both node and interface as key
|
||||
|
||||
# Adamson change: first check for iface config keyed by "node:ifc.name"
|
||||
# (so that nodes w/ multiple interfaces of same conftype can have
|
||||
# different configs for each separate interface)
|
||||
key = 1000 * ifc.node.objid
|
||||
if ifc.netindex is not None:
|
||||
key += ifc.netindex
|
||||
|
||||
# try retrieve interface specific configuration
|
||||
config = self.get_configs(key, config_type)
|
||||
|
||||
# otherwise retrieve the interfaces node configuration
|
||||
if not config:
|
||||
config = self.get_configs(ifc.node.objid, config_type)
|
||||
|
||||
if not config and ifc.transport_type == "raw":
|
||||
# with EMANE 0.9.2+, we need an extra NEM XML from
|
||||
# model.buildnemxmlfiles(), so defaults are returned here
|
||||
config = self.get_configs(node_id, config_type) or default_values
|
||||
|
||||
return config
|
||||
|
||||
def setup(self):
|
||||
"""
|
||||
Populate self._objs with EmaneNodes; perform distributed setup;
|
||||
|
@ -284,7 +254,7 @@ class EmaneManager(ConfigurableManager):
|
|||
# - needs to be configured before checkdistributed() for distributed
|
||||
# - needs to exist when eventservice binds to it (initeventservice)
|
||||
if self.session.master:
|
||||
otadev = self.get_config("otamanagerdevice")
|
||||
otadev = self.emane_config.get_config("otamanagerdevice")
|
||||
netidx = self.session.get_control_net_index(otadev)
|
||||
logger.debug("emane ota manager device: index(%s) otadev(%s)", netidx, otadev)
|
||||
if netidx < 0:
|
||||
|
@ -293,7 +263,7 @@ class EmaneManager(ConfigurableManager):
|
|||
|
||||
ctrlnet = self.session.add_remove_control_net(net_index=netidx, remove=False, conf_required=False)
|
||||
self.distributedctrlnet(ctrlnet)
|
||||
eventdev = self.get_config("eventservicedevice")
|
||||
eventdev = self.emane_config.get_config("eventservicedevice")
|
||||
logger.debug("emane event service device: eventdev(%s)", eventdev)
|
||||
if eventdev != otadev:
|
||||
netidx = self.session.get_control_net_index(eventdev)
|
||||
|
@ -309,11 +279,11 @@ class EmaneManager(ConfigurableManager):
|
|||
# we are slave, but haven't received a platformid yet
|
||||
platform_id_start = "platform_id_start"
|
||||
default_values = self.emane_config.default_values()
|
||||
value = self.get_config(platform_id_start)
|
||||
value = self.emane_config.get_config(platform_id_start)
|
||||
if value == default_values[platform_id_start]:
|
||||
return EmaneManager.NOT_READY
|
||||
|
||||
self.setnodemodels()
|
||||
self.check_node_models()
|
||||
return EmaneManager.SUCCESS
|
||||
|
||||
def startup(self):
|
||||
|
@ -441,10 +411,10 @@ class EmaneManager(ConfigurableManager):
|
|||
emane_node = self._emane_nodes[key]
|
||||
nemcount += emane_node.numnetif()
|
||||
|
||||
nemid = int(self.get_config("nem_id_start"))
|
||||
nemid = int(self.emane_config.get_config("nem_id_start"))
|
||||
nemid += nemcount
|
||||
|
||||
platformid = int(self.get_config("platform_id_start"))
|
||||
platformid = int(self.emane_config.get_config("platform_id_start"))
|
||||
|
||||
# build an ordered list of servers so platform ID is deterministic
|
||||
servers = []
|
||||
|
@ -463,8 +433,8 @@ class EmaneManager(ConfigurableManager):
|
|||
|
||||
platformid += 1
|
||||
typeflags = ConfigFlags.UPDATE.value
|
||||
self.set_config("platform_id_start", str(platformid))
|
||||
self.set_config("nem_id_start", str(nemid))
|
||||
self.emane_config.set_config("platform_id_start", str(platformid))
|
||||
self.emane_config.set_config("nem_id_start", str(nemid))
|
||||
config_data = ConfigShim.config_data(0, None, typeflags, self.emane_config, self.get_configs())
|
||||
message = dataconversion.convert_config(config_data)
|
||||
server.sock.send(message)
|
||||
|
@ -489,6 +459,7 @@ class EmaneManager(ConfigurableManager):
|
|||
self.buildnemxml()
|
||||
self.buildeventservicexml()
|
||||
|
||||
# TODO: remove need for tlv messaging
|
||||
def distributedctrlnet(self, ctrlnet):
|
||||
"""
|
||||
Distributed EMANE requires multiple control network prefixes to
|
||||
|
@ -566,33 +537,30 @@ class EmaneManager(ConfigurableManager):
|
|||
with open(pathname, "w") as xml_file:
|
||||
doc.writexml(writer=xml_file, indent="", addindent=" ", newl="\n", encoding="UTF-8")
|
||||
|
||||
def setnodemodels(self):
|
||||
def check_node_models(self):
|
||||
"""
|
||||
Associate EmaneModel classes with EmaneNode nodes. The model
|
||||
configurations are stored in self.configs.
|
||||
"""
|
||||
for key in self._emane_nodes:
|
||||
self.setnodemodel(key)
|
||||
for node_id in self._emane_nodes:
|
||||
emane_node = self._emane_nodes[node_id]
|
||||
logger.debug("checking emane model for node: %s", node_id)
|
||||
|
||||
def setnodemodel(self, node_id):
|
||||
logger.debug("setting emane models for node: %s", node_id)
|
||||
node_config_types = self.get_all_configs(node_id)
|
||||
if not node_config_types:
|
||||
logger.debug("no emane node model configuration, leaving: %s", node_id)
|
||||
return False
|
||||
# skip nodes that already have a model set
|
||||
if emane_node.model:
|
||||
logger.debug("node(%s) already has model(%s)", emane_node.objid, emane_node.model.name)
|
||||
continue
|
||||
|
||||
# retrieve and use the last set model configured for this node
|
||||
# this supports behavior from the legacy gui due to there not being a formal set model message
|
||||
emane_node = self._emane_nodes[node_id]
|
||||
models = self.getmodels(emane_node)
|
||||
if models:
|
||||
model_class, config = models[-1]
|
||||
# set model configured for node, due to legacy messaging configuration before nodes exist
|
||||
model_name = self.node_models.get(node_id)
|
||||
if not model_name:
|
||||
logger.error("emane node(%s) has no node model", node_id)
|
||||
raise ValueError("emane node has no model set")
|
||||
|
||||
model_class = self._modelclsmap[model_name]
|
||||
config = model_class.get_configs(node_id=node_id)
|
||||
logger.debug("setting emane model(%s) config(%s)", model_class, config)
|
||||
emane_node.setmodel(model_class, config)
|
||||
return True
|
||||
|
||||
# no model has been configured for this EmaneNode
|
||||
return False
|
||||
|
||||
def nemlookup(self, nemid):
|
||||
"""
|
||||
|
@ -631,10 +599,10 @@ class EmaneManager(ConfigurableManager):
|
|||
plat = doc.getElementsByTagName("platform").pop()
|
||||
|
||||
if otadev:
|
||||
self.set_config("otamanagerdevice", otadev)
|
||||
self.emane_config.set_config("otamanagerdevice", otadev)
|
||||
|
||||
if eventdev:
|
||||
self.set_config("eventservicedevice", eventdev)
|
||||
self.emane_config.set_config("eventservicedevice", eventdev)
|
||||
|
||||
# append all platform options (except starting id) to doc
|
||||
for configuration in self.emane_config.emulator_config:
|
||||
|
@ -642,7 +610,7 @@ class EmaneManager(ConfigurableManager):
|
|||
if name == "platform_id_start":
|
||||
continue
|
||||
|
||||
value = self.get_config(name)
|
||||
value = self.emane_config.get_config(name)
|
||||
param = self.xmlparam(doc, name, value)
|
||||
plat.appendChild(param)
|
||||
|
||||
|
@ -652,7 +620,7 @@ class EmaneManager(ConfigurableManager):
|
|||
"""
|
||||
Build a platform.xml file now that all nodes are configured.
|
||||
"""
|
||||
nemid = int(self.get_config("nem_id_start"))
|
||||
nemid = int(self.emane_config.get_config("nem_id_start"))
|
||||
platformxmls = {}
|
||||
|
||||
# assume self._objslock is already held here
|
||||
|
@ -729,7 +697,7 @@ class EmaneManager(ConfigurableManager):
|
|||
default_values = self.emane_config.default_values()
|
||||
for name in ["eventservicegroup", "eventservicedevice"]:
|
||||
a = default_values[name]
|
||||
b = self.get_config(name)
|
||||
b = self.emane_config.get_config(name)
|
||||
if a != b:
|
||||
need_xml = True
|
||||
|
||||
|
@ -739,12 +707,12 @@ class EmaneManager(ConfigurableManager):
|
|||
return
|
||||
|
||||
try:
|
||||
group, port = self.get_config("eventservicegroup").split(":")
|
||||
group, port = self.emane_config.get_config("eventservicegroup").split(":")
|
||||
except ValueError:
|
||||
logger.exception("invalid eventservicegroup in EMANE config")
|
||||
return
|
||||
|
||||
dev = self.get_config("eventservicedevice")
|
||||
dev = self.emane_config.get_config("eventservicedevice")
|
||||
doc = self.xmldoc("emaneeventmsgsvc")
|
||||
es = doc.getElementsByTagName("emaneeventmsgsvc").pop()
|
||||
kvs = (("group", group), ("port", port), ("device", dev), ("mcloop", "1"), ("ttl", "32"))
|
||||
|
@ -771,12 +739,12 @@ class EmaneManager(ConfigurableManager):
|
|||
if realtime:
|
||||
emanecmd += "-r",
|
||||
|
||||
otagroup, otaport = self.get_config("otamanagergroup").split(":")
|
||||
otadev = self.get_config("otamanagerdevice")
|
||||
otagroup, otaport = self.emane_config.get_config("otamanagergroup").split(":")
|
||||
otadev = self.emane_config.get_config("otamanagerdevice")
|
||||
otanetidx = self.session.get_control_net_index(otadev)
|
||||
|
||||
eventgroup, eventport = self.get_config("eventservicegroup").split(":")
|
||||
eventdev = self.get_config("eventservicedevice")
|
||||
eventgroup, eventport = self.emane_config.get_config("eventservicegroup").split(":")
|
||||
eventdev = self.emane_config.get_config("eventservicedevice")
|
||||
eventservicenetidx = self.session.get_control_net_index(eventdev)
|
||||
|
||||
run_emane_on_host = False
|
||||
|
@ -1013,6 +981,7 @@ class EmaneGlobalModel(EmaneModel):
|
|||
_DEFAULT_DEV = "ctrl0"
|
||||
|
||||
name = "emane"
|
||||
configuration_maps = {}
|
||||
|
||||
emulator_xml = "/usr/share/emane/manifest/nemmanager.xml"
|
||||
emulator_defaults = {
|
||||
|
|
|
@ -70,9 +70,6 @@ class EmaneModel(WirelessModel):
|
|||
config_len = len(cls.configurations())
|
||||
return "MAC Parameters:1-%d|PHY Parameters:%d-%d" % (mac_len, mac_len + 1, config_len)
|
||||
|
||||
def __init__(self, session, object_id=None):
|
||||
super(EmaneModel, self).__init__(session, object_id)
|
||||
|
||||
def build_xml_files(self, emane_manager, interface):
|
||||
"""
|
||||
Builds xml files for emane. Includes a nem.xml file that points to both mac.xml and phy.xml definitions.
|
||||
|
@ -82,7 +79,7 @@ class EmaneModel(WirelessModel):
|
|||
:return: nothing
|
||||
"""
|
||||
# retrieve configuration values
|
||||
config = emane_manager.getifcconfig(self.object_id, self.name, self.default_values(), interface)
|
||||
config = self.getifcconfig(self.object_id, interface)
|
||||
if not config:
|
||||
return
|
||||
|
||||
|
@ -270,11 +267,10 @@ class EmaneModel(WirelessModel):
|
|||
:rtype: str
|
||||
"""
|
||||
name = "n%s" % self.object_id
|
||||
emane_manager = self.session.emane
|
||||
|
||||
if interface:
|
||||
node_id = interface.node.objid
|
||||
if emane_manager.getifcconfig(node_id, self.name, {}, interface):
|
||||
if self.getifcconfig(node_id, interface):
|
||||
name = interface.localname.replace(".", "_")
|
||||
|
||||
return "%s%s" % (name, self.name)
|
||||
|
@ -353,3 +349,43 @@ class EmaneModel(WirelessModel):
|
|||
:return: nothing
|
||||
"""
|
||||
logger.warn("emane model(%s) does not support link configuration", self.name)
|
||||
|
||||
def getifcconfig(self, node_id, ifc):
|
||||
"""
|
||||
Retrieve interface configuration or node configuration if not provided.
|
||||
|
||||
:param int node_id: node id
|
||||
:param ifc: node interface
|
||||
:return:
|
||||
"""
|
||||
# use the network-wide config values or interface(NEM)-specific values?
|
||||
if ifc is None:
|
||||
return self.get_configs(node_id)
|
||||
else:
|
||||
# don"t use default values when interface config is the same as net
|
||||
# note here that using ifc.node.objid as key allows for only one type
|
||||
# of each model per node;
|
||||
# TODO: use both node and interface as key
|
||||
|
||||
# Adamson change: first check for iface config keyed by "node:ifc.name"
|
||||
# (so that nodes w/ multiple interfaces of same conftype can have
|
||||
# different configs for each separate interface)
|
||||
key = 1000 * ifc.node.objid
|
||||
if ifc.netindex is not None:
|
||||
key += ifc.netindex
|
||||
|
||||
# try retrieve interface specific configuration, avoid getting defaults
|
||||
config = {}
|
||||
if key in self.configuration_maps:
|
||||
config = self.get_configs(key)
|
||||
|
||||
# otherwise retrieve the interfaces node configuration, avoid using defaults
|
||||
if not config and ifc.node.objid in self.configuration_maps:
|
||||
config = self.get_configs(ifc.node.objid)
|
||||
|
||||
if not config and ifc.transport_type == "raw":
|
||||
# with EMANE 0.9.2+, we need an extra NEM XML from
|
||||
# model.buildnemxmlfiles(), so defaults are returned here
|
||||
config = self.get_configs(node_id)
|
||||
|
||||
return config
|
||||
|
|
|
@ -9,6 +9,7 @@ from core.emane import emanemodel
|
|||
class EmaneIeee80211abgModel(emanemodel.EmaneModel):
|
||||
# model name
|
||||
name = "emane_ieee80211abg"
|
||||
configuration_maps = {}
|
||||
|
||||
# mac configuration
|
||||
mac_library = "ieee80211abgmaclayer"
|
||||
|
|
|
@ -67,7 +67,13 @@ class EmaneNode(EmaneNet):
|
|||
def unlink(self, netif1, netif2):
|
||||
pass
|
||||
|
||||
def setmodel(self, model, config):
|
||||
def updatemodel(self, config):
|
||||
if not self.model:
|
||||
raise ValueError("no model set to update for node(%s)", self.objid)
|
||||
logger.info("node(%s) updating model(%s): %s", self.objid, self.model.name, config)
|
||||
self.model.set_configs(config, node_id=self.objid)
|
||||
|
||||
def setmodel(self, model, config=None):
|
||||
"""
|
||||
set the EmaneModel associated with this node
|
||||
"""
|
||||
|
@ -75,7 +81,7 @@ class EmaneNode(EmaneNet):
|
|||
if model.config_type == RegisterTlvs.WIRELESS.value:
|
||||
# EmaneModel really uses values from ConfigurableManager
|
||||
# when buildnemxml() is called, not during init()
|
||||
self.model = model(session=self.session, object_id=self.objid)
|
||||
self.model = model(session=self.session, object_id=self.objid, config=config)
|
||||
elif model.config_type == RegisterTlvs.MOBILITY.value:
|
||||
self.mobility = model(session=self.session, object_id=self.objid, config=config)
|
||||
|
||||
|
@ -174,7 +180,8 @@ class EmaneNode(EmaneNet):
|
|||
trans.setAttribute("library", "trans%s" % transport_type.lower())
|
||||
trans.appendChild(emane.xmlparam(transdoc, "bitrate", "0"))
|
||||
|
||||
config = emane.get_configs(self.objid, self.model.name)
|
||||
model_class = emane.get_model_class(self.model.name)
|
||||
config = model_class.get_configs(self.objid)
|
||||
logger.debug("transport xml config: %s", config)
|
||||
flowcontrol = config.get("flowcontrolenable", "0") == "1"
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ from core.emane import emanemodel
|
|||
class EmaneRfPipeModel(emanemodel.EmaneModel):
|
||||
# model name
|
||||
name = "emane_rfpipe"
|
||||
configuration_maps = {}
|
||||
|
||||
# mac configuration
|
||||
mac_library = "rfpipemaclayer"
|
||||
|
|
|
@ -16,6 +16,7 @@ from core.misc import utils
|
|||
class EmaneTdmaModel(emanemodel.EmaneModel):
|
||||
# model name
|
||||
name = "emane_tdma"
|
||||
configuration_maps = {}
|
||||
|
||||
# mac configuration
|
||||
mac_library = "tdmaeventschedulerradiomodel"
|
||||
|
@ -47,7 +48,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
|
|||
:return: nothing
|
||||
"""
|
||||
# get configured schedule
|
||||
config = emane_manager.get_configs(self.object_id, self.name)
|
||||
config = self.get_configs(self.object_id)
|
||||
if not config:
|
||||
return
|
||||
schedule = config[self.schedule_name]
|
||||
|
|
|
@ -325,9 +325,6 @@ class EmuSession(Session):
|
|||
:param core.enumerations.LinkTypes link_type: link type to delete
|
||||
:return: nothing
|
||||
"""
|
||||
# interface data
|
||||
# interface_one_data, interface_two_data = get_interfaces(link_data)
|
||||
|
||||
# get node objects identified by link data
|
||||
node_one, node_two, net_one, net_two, tunnel = self._link_nodes(node_one_id, node_two_id)
|
||||
|
||||
|
@ -390,9 +387,6 @@ class EmuSession(Session):
|
|||
:param core.emulator.emudata.LinkOptions link_options: data to update link with
|
||||
:return: nothing
|
||||
"""
|
||||
# interface data
|
||||
# interface_one_data, interface_two_data = get_interfaces(link_data)
|
||||
|
||||
# get node objects identified by link data
|
||||
node_one, node_two, net_one, net_two, tunnel = self._link_nodes(node_one_id, node_two_id)
|
||||
|
||||
|
@ -801,33 +795,9 @@ class EmuSession(Session):
|
|||
|
||||
# create and return network
|
||||
emane_network = self.add_node(_type=NodeTypes.EMANE, node_options=node_options)
|
||||
self.set_emane_model(emane_network, model)
|
||||
emane_network.setmodel(model)
|
||||
return emane_network
|
||||
|
||||
def set_emane_model(self, emane_node, emane_model):
|
||||
"""
|
||||
Set emane model for a given emane node.
|
||||
|
||||
:param emane_node: emane node to set model for
|
||||
:param emane_model: emane model to set
|
||||
:return: nothing
|
||||
"""
|
||||
config = emane_model.default_values()
|
||||
emane_node.setmodel(emane_model, config)
|
||||
self.emane.set_configs(config, emane_node.objid, emane_model.name)
|
||||
|
||||
def set_wireless_model(self, node, model):
|
||||
"""
|
||||
Convenience method for setting a wireless model.
|
||||
|
||||
:param node: node to set wireless model for
|
||||
:param core.mobility.WirelessModel model: wireless model to set node to
|
||||
:return: nothing
|
||||
"""
|
||||
config = model.default_values()
|
||||
node.setmodel(model, config)
|
||||
self.mobility.set_configs(config, node.objid, model.name)
|
||||
|
||||
def wireless_link_all(self, network, nodes):
|
||||
"""
|
||||
Link all nodes to the provided wireless network.
|
||||
|
|
|
@ -11,7 +11,6 @@ import time
|
|||
from core import logger
|
||||
from core.conf import ConfigurableOptions
|
||||
from core.conf import Configuration
|
||||
from core.conf import ConfigurableManager
|
||||
from core.coreobj import PyCoreNode
|
||||
from core.data import EventData
|
||||
from core.data import LinkData
|
||||
|
@ -26,7 +25,7 @@ from core.misc import utils
|
|||
from core.misc.ipaddress import IpAddress
|
||||
|
||||
|
||||
class MobilityManager(ConfigurableManager):
|
||||
class MobilityManager(object):
|
||||
"""
|
||||
Member of session class for handling configuration data for mobility and
|
||||
range models.
|
||||
|
@ -40,7 +39,6 @@ class MobilityManager(ConfigurableManager):
|
|||
|
||||
:param core.session.Session session: session this manager is tied to
|
||||
"""
|
||||
super(MobilityManager, self).__init__()
|
||||
self.session = session
|
||||
# configurations for basic range, indexed by WLAN node number, are stored in configurations
|
||||
# mapping from model names to their classes
|
||||
|
@ -69,13 +67,19 @@ class MobilityManager(ConfigurableManager):
|
|||
:return: list of model and values tuples for the network node
|
||||
:rtype: list
|
||||
"""
|
||||
configs = self.get_all_configs(node.objid)
|
||||
models = []
|
||||
for model_name, config in configs.iteritems():
|
||||
model_class = self._modelclsmap[model_name]
|
||||
models.append((model_class, config))
|
||||
for model_class in self._modelclsmap.itervalues():
|
||||
if node.objid in model_class.configuration_maps:
|
||||
config = model_class.get_configs(node_id=node.objid)
|
||||
models.append((model_class, config))
|
||||
return models
|
||||
|
||||
def nodes(self):
|
||||
node_ids = set()
|
||||
for model_class in self._modelclsmap.itervalues():
|
||||
node_ids |= model_class.nodes()
|
||||
return node_ids
|
||||
|
||||
def startup(self, node_ids=None):
|
||||
"""
|
||||
Session is transitioning from instantiation to runtime state.
|
||||
|
@ -96,20 +100,13 @@ class MobilityManager(ConfigurableManager):
|
|||
logger.warn("skipping mobility configuration for unknown node: %s", node_id)
|
||||
continue
|
||||
|
||||
node_configs = self.get_all_configs(node_id)
|
||||
if not node_configs:
|
||||
logger.warn("missing mobility configuration for node: %s", node_id)
|
||||
continue
|
||||
|
||||
for model_name in node_configs.iterkeys():
|
||||
try:
|
||||
clazz = self._modelclsmap[model_name]
|
||||
model_config = self.get_configs(node_id, model_name)
|
||||
logger.info("setting mobility model(%s) to node: %s", model_name, model_config)
|
||||
node.setmodel(clazz, model_config)
|
||||
except KeyError:
|
||||
logger.exception("skipping mobility configuration for unknown model: %s", model_name)
|
||||
for model_class in self._modelclsmap.itervalues():
|
||||
logger.debug("model(%s) configurations: %s", model_class, model_class.configuration_maps)
|
||||
if node_id not in model_class.configuration_maps:
|
||||
continue
|
||||
config = model_class.get_configs(node_id=node_id)
|
||||
logger.info("setting mobility model(%s) to node: %s", model_class.name, config)
|
||||
node.setmodel(model_class, config)
|
||||
|
||||
if self.session.master:
|
||||
self.installphysnodes(node)
|
||||
|
@ -117,37 +114,15 @@ class MobilityManager(ConfigurableManager):
|
|||
if node.mobility:
|
||||
self.session.event_loop.add_event(0.0, node.mobility.startup)
|
||||
|
||||
def reset(self):
|
||||
def config_reset(self, node_id=None):
|
||||
"""
|
||||
Reset all configs.
|
||||
|
||||
:param int node_id: node configuration to reset or None for all configurations
|
||||
:return: nothing
|
||||
"""
|
||||
self.config_reset()
|
||||
|
||||
def set_configs(self, config, node_id=None, config_type=None):
|
||||
"""
|
||||
Adds a check for run-time updates for WLANs after providing normal set configs.
|
||||
|
||||
:param dict config: configuration value
|
||||
:param int node_id: node id
|
||||
:param str config_type: configuration type
|
||||
:return: nothing
|
||||
"""
|
||||
if not node_id or not config_type:
|
||||
raise ValueError("mobility manager invalid node id or config type: %s - %s", node_id, config_type)
|
||||
|
||||
super(MobilityManager, self).set_configs(config, node_id, config_type)
|
||||
|
||||
if self.session is None:
|
||||
return
|
||||
|
||||
if self.session.state == EventTypes.RUNTIME_STATE.value:
|
||||
try:
|
||||
node = self.session.get_object(node_id)
|
||||
node.updatemodel(config_type, config)
|
||||
except KeyError:
|
||||
logger.exception("skipping mobility configuration for unknown node %s", node_id)
|
||||
for model in self._modelclsmap.itervalues():
|
||||
model.config_reset(node_id=node_id)
|
||||
|
||||
def handleevent(self, event_data):
|
||||
"""
|
||||
|
@ -338,6 +313,8 @@ class WirelessModel(ConfigurableOptions):
|
|||
"""
|
||||
self.session = session
|
||||
self.object_id = object_id
|
||||
if config:
|
||||
self.set_configs(config, node_id=self.object_id)
|
||||
|
||||
def all_link_data(self, flags):
|
||||
"""
|
||||
|
@ -360,12 +337,11 @@ class WirelessModel(ConfigurableOptions):
|
|||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def updateconfig(self, config):
|
||||
def updateconfig(self):
|
||||
"""
|
||||
For run-time updates of model config. Returns True when position callback and set link
|
||||
parameters should be invoked.
|
||||
|
||||
:param dict config: value to update
|
||||
:return: False
|
||||
:rtype: bool
|
||||
"""
|
||||
|
@ -379,6 +355,7 @@ class BasicRangeModel(WirelessModel):
|
|||
the GUI.
|
||||
"""
|
||||
name = "basic_range"
|
||||
configuration_maps = {}
|
||||
|
||||
@classmethod
|
||||
def configurations(cls):
|
||||
|
@ -409,10 +386,8 @@ class BasicRangeModel(WirelessModel):
|
|||
self._netifs = {}
|
||||
self._netifslock = threading.Lock()
|
||||
|
||||
# TODO: can this be handled in a better spot
|
||||
if not config:
|
||||
config = self.default_values()
|
||||
self.session.mobility.set_configs(config, node_id=object_id, config_type=self.name)
|
||||
# retrieve current configuration
|
||||
config = self.get_configs(node_id=self.object_id)
|
||||
|
||||
self.range = None
|
||||
self.bw = None
|
||||
|
@ -571,17 +546,17 @@ class BasicRangeModel(WirelessModel):
|
|||
c = p1[2] - p2[2]
|
||||
return math.hypot(math.hypot(a, b), c)
|
||||
|
||||
def updateconfig(self, config):
|
||||
def updateconfig(self):
|
||||
"""
|
||||
Configuration has changed during runtime.
|
||||
MobilityManager.setconfig() -> WlanNode.updatemodel() ->
|
||||
WirelessModel.updateconfig()
|
||||
|
||||
:param dict config: values to update configuration
|
||||
:return: was update successful
|
||||
:rtype: bool
|
||||
"""
|
||||
config = self.get_configs(node_id=self.object_id)
|
||||
self.values_from_config(config)
|
||||
self.setlinkparams()
|
||||
return True
|
||||
|
||||
def create_link_data(self, interface1, interface2, message_type):
|
||||
|
@ -840,7 +815,6 @@ class WayPointMobility(WirelessModel):
|
|||
self.setnodeposition(node, x, y, z)
|
||||
moved.append(node)
|
||||
moved_netifs.append(netif)
|
||||
# self.wlan.model.update(moved)
|
||||
self.session.mobility.updatewlans(moved, moved_netifs)
|
||||
|
||||
def addwaypoint(self, time, nodenum, x, y, z, speed):
|
||||
|
@ -914,7 +888,6 @@ class WayPointMobility(WirelessModel):
|
|||
:return: nothing
|
||||
"""
|
||||
# this would cause PyCoreNetIf.poshook() callback (range calculation)
|
||||
# node.setposition(x, y, z)
|
||||
node.position.set(x, y, z)
|
||||
node_data = node.data(message_type=0)
|
||||
self.session.broadcast_node(node_data)
|
||||
|
@ -984,6 +957,7 @@ class Ns2ScriptedMobility(WayPointMobility):
|
|||
BonnMotion.
|
||||
"""
|
||||
name = "ns2script"
|
||||
configuration_maps = {}
|
||||
|
||||
@classmethod
|
||||
def configurations(cls):
|
||||
|
@ -1014,9 +988,8 @@ class Ns2ScriptedMobility(WayPointMobility):
|
|||
self._netifs = {}
|
||||
self._netifslock = threading.Lock()
|
||||
|
||||
if not config:
|
||||
config = self.default_values()
|
||||
self.session.mobility.set_configs(config, node_id=object_id, config_type=self.name)
|
||||
# retrieve current configuration
|
||||
config = self.get_configs(self.object_id)
|
||||
|
||||
self.file = config["file"]
|
||||
self.refresh_ms = int(config["refresh_ms"])
|
||||
|
@ -1041,9 +1014,9 @@ class Ns2ScriptedMobility(WayPointMobility):
|
|||
"""
|
||||
filename = self.findfile(self.file)
|
||||
try:
|
||||
f = open(filename, 'r')
|
||||
f = open(filename, "r")
|
||||
except IOError:
|
||||
logger.exception("ns-2 scripted mobility failed to load file '%s'", self.file)
|
||||
logger.exception("ns-2 scripted mobility failed to load file: %s", self.file)
|
||||
return
|
||||
logger.info("reading ns-2 script file: %s" % filename)
|
||||
ln = 0
|
||||
|
|
|
@ -377,7 +377,7 @@ class WlanNode(LxBrNet):
|
|||
# invokes any netif.poshook
|
||||
netif.setposition(x, y, z)
|
||||
|
||||
def setmodel(self, model, config):
|
||||
def setmodel(self, model, config=None):
|
||||
"""
|
||||
Sets the mobility and wireless model.
|
||||
|
||||
|
@ -398,31 +398,23 @@ class WlanNode(LxBrNet):
|
|||
elif model.config_type == RegisterTlvs.MOBILITY.value:
|
||||
self.mobility = model(session=self.session, object_id=self.objid, config=config)
|
||||
|
||||
def updatemodel(self, model_name, config):
|
||||
"""
|
||||
Allow for model updates during runtime (similar to setmodel().)
|
||||
def update_mobility(self, config):
|
||||
if not self.mobility:
|
||||
raise ValueError("no mobility set to update for node(%s)", self.objid)
|
||||
self.mobility.set_configs(config, node_id=self.objid)
|
||||
|
||||
:param str model_name: model name to update
|
||||
:param dict config: values to update model with
|
||||
:return: nothing
|
||||
"""
|
||||
logger.info("updating model %s" % model_name)
|
||||
if self.model is None or self.model.name != model_name:
|
||||
return
|
||||
|
||||
model = self.model
|
||||
if model.config_type == RegisterTlvs.WIRELESS.value:
|
||||
if not model.updateconfig(config):
|
||||
return
|
||||
|
||||
if self.model.position_callback:
|
||||
for netif in self.netifs():
|
||||
netif.poshook = self.model.position_callback
|
||||
if netif.node is not None:
|
||||
x, y, z = netif.node.position.get()
|
||||
netif.poshook(netif, x, y, z)
|
||||
|
||||
self.model.setlinkparams()
|
||||
def updatemodel(self, config):
|
||||
if not self.model:
|
||||
raise ValueError("no model set to update for node(%s)", self.objid)
|
||||
logger.info("node(%s) updating model(%s): %s", self.objid, self.model.name, config)
|
||||
self.model.set_configs(config, node_id=self.objid)
|
||||
if self.model.position_callback:
|
||||
for netif in self.netifs():
|
||||
netif.poshook = self.model.position_callback
|
||||
if netif.node is not None:
|
||||
x, y, z = netif.node.position.get()
|
||||
netif.poshook(netif, x, y, z)
|
||||
self.model.updateconfig()
|
||||
|
||||
def all_link_data(self, flags):
|
||||
"""
|
||||
|
|
|
@ -305,7 +305,7 @@ class OvsNet(PyCoreNet):
|
|||
utils.check_cmd([constants.OVS_BIN, "add-port", network.bridge_name, interface.name])
|
||||
utils.check_cmd([constants.IP_BIN, "link", "set", interface.name, "up"])
|
||||
|
||||
# TODO: is there a native method for this? see if this causes issues
|
||||
# TODO: is there a native method for this? see if this causes issues
|
||||
# i = network.newifindex()
|
||||
# network._netif[i] = interface
|
||||
# with network._linked_lock:
|
||||
|
@ -593,7 +593,7 @@ class OvsWlanNode(OvsNet):
|
|||
interface.setposition(x, y, z)
|
||||
# self.model.setlinkparams()
|
||||
|
||||
def setmodel(self, model, config):
|
||||
def setmodel(self, model, config=None):
|
||||
"""
|
||||
Mobility and wireless model.
|
||||
"""
|
||||
|
@ -611,29 +611,18 @@ class OvsWlanNode(OvsNet):
|
|||
elif model.type == RegisterTlvs.MOBILITY.value:
|
||||
self.mobility = model(session=self.session, object_id=self.objid, config=config)
|
||||
|
||||
def updatemodel(self, model_name, values):
|
||||
"""
|
||||
Allow for model updates during runtime (similar to setmodel().)
|
||||
"""
|
||||
logger.info("updating model %s", model_name)
|
||||
if self.model is None or self.model.name != model_name:
|
||||
logger.info(
|
||||
"failure to update model, model doesn't exist or invalid name: model(%s) - name(%s)",
|
||||
self.model, model_name
|
||||
)
|
||||
return
|
||||
|
||||
model = self.model
|
||||
if model.type == RegisterTlvs.WIRELESS.value:
|
||||
if not model.updateconfig(values):
|
||||
return
|
||||
if self.model.position_callback:
|
||||
for interface in self.netifs():
|
||||
interface.poshook = self.model.position_callback
|
||||
if interface.node is not None:
|
||||
x, y, z = interface.node.position.get()
|
||||
interface.poshook(interface, x, y, z)
|
||||
self.model.setlinkparams()
|
||||
def updatemodel(self, config):
|
||||
if not self.model:
|
||||
raise ValueError("no model set to update for node(%s)", self.objid)
|
||||
logger.info("node(%s) updating model(%s): %s", self.objid, self.model.name, config)
|
||||
self.model.set_configs(config, node_id=self.objid)
|
||||
if self.model.position_callback:
|
||||
for netif in self.netifs():
|
||||
netif.poshook = self.model.position_callback
|
||||
if netif.node is not None:
|
||||
x, y, z = netif.node.position.get()
|
||||
netif.poshook(netif, x, y, z)
|
||||
self.model.updateconfig()
|
||||
|
||||
def all_link_data(self, flags):
|
||||
all_links = OvsNet.all_link_data(self, flags)
|
||||
|
|
|
@ -19,10 +19,8 @@ from core import constants
|
|||
from core import logger
|
||||
from core.api import coreapi
|
||||
from core.broker import CoreBroker
|
||||
from core.conf import ConfigShim
|
||||
from core.conf import ConfigurableOptions
|
||||
from core.conf import ConfigShim, ConfigurableOptions
|
||||
from core.conf import Configuration
|
||||
from core.conf import ConfigurableManager
|
||||
from core.data import ConfigData
|
||||
from core.data import EventData
|
||||
from core.data import ExceptionData
|
||||
|
@ -1149,16 +1147,24 @@ class Session(object):
|
|||
self.broadcast_config(config_data)
|
||||
|
||||
# send emane model info
|
||||
for node_id in self.emane.nodes():
|
||||
if node_id not in self.objects:
|
||||
continue
|
||||
|
||||
node = self.get_object(node_id)
|
||||
for model_class, config in self.emane.getmodels(node):
|
||||
for model_name in self.emane.emane_models():
|
||||
model_class = self.emane.get_model_class(model_name)
|
||||
for node_id in model_class.nodes():
|
||||
config = model_class.get_configs(node_id)
|
||||
logger.info("emane config: node(%s) class(%s) values(%s)", node_id, model_class, config)
|
||||
config_data = ConfigShim.config_data(0, node_id, ConfigFlags.UPDATE.value, model_class, config)
|
||||
self.broadcast_config(config_data)
|
||||
|
||||
# for node_id in self.emane.nodes():
|
||||
# if node_id not in self.objects:
|
||||
# continue
|
||||
#
|
||||
# node = self.get_object(node_id)
|
||||
# for model_class, config in self.emane.getmodels(node):
|
||||
# logger.info("emane config: node(%s) class(%s) values(%s)", node_id, model_class, config)
|
||||
# config_data = ConfigShim.config_data(0, node_id, ConfigFlags.UPDATE.value, model_class, config)
|
||||
# self.broadcast_config(config_data)
|
||||
|
||||
# service customizations
|
||||
service_configs = self.services.getallconfigs()
|
||||
for node_id, service in service_configs:
|
||||
|
@ -1221,11 +1227,12 @@ class Session(object):
|
|||
logger.info("informed GUI about %d nodes and %d links", len(nodes_data), len(links_data))
|
||||
|
||||
|
||||
class SessionConfig(ConfigurableManager, ConfigurableOptions):
|
||||
class SessionConfig(ConfigurableOptions):
|
||||
"""
|
||||
Session configuration object.
|
||||
"""
|
||||
name = "session"
|
||||
configuration_maps = {}
|
||||
config_type = RegisterTlvs.UTILITY.value
|
||||
|
||||
@classmethod
|
||||
|
@ -1251,16 +1258,16 @@ class SessionConfig(ConfigurableManager, ConfigurableOptions):
|
|||
return "Options:1-%d" % len(cls.configurations())
|
||||
|
||||
def __init__(self):
|
||||
super(SessionConfig, self).__init__()
|
||||
config = self.default_values()
|
||||
self.set_configs(config)
|
||||
self.set_configs()
|
||||
|
||||
|
||||
class SessionMetaData(ConfigurableManager):
|
||||
class SessionMetaData(ConfigurableOptions):
|
||||
"""
|
||||
Metadata is simply stored in a configs[] dict. Key=value pairs are
|
||||
passed in from configure messages destined to the "metadata" object.
|
||||
The data is not otherwise interpreted or processed.
|
||||
"""
|
||||
name = "metadata"
|
||||
configuration_maps = {}
|
||||
|
||||
config_type = RegisterTlvs.UTILITY.value
|
||||
|
|
|
@ -210,9 +210,12 @@ class CoreDocumentParser1(object):
|
|||
raise NotImplementedError
|
||||
logger.info("setting wireless link params: node(%s) model(%s) mobility_model(%s)",
|
||||
nodenum, model_name, mobility_model_name)
|
||||
mgr.setconfig_keyvalues(nodenum, model_name, link_params.items())
|
||||
model_class = mgr.get_model_class(model_name)
|
||||
model_class.set_configs(link_params, node_id=nodenum)
|
||||
|
||||
if mobility_model_name and mobility_params:
|
||||
mgr.setconfig_keyvalues(nodenum, mobility_model_name, mobility_params.items())
|
||||
model_class = mgr.get_model_class(mobility_model_name)
|
||||
model_class.set_configs(mobility_params, node_id=nodenum)
|
||||
|
||||
def link_layer2_devices(self, device1, ifname1, device2, ifname2):
|
||||
"""
|
||||
|
@ -843,7 +846,7 @@ class CoreDocumentParser1(object):
|
|||
params = self.parse_parameter_children(metadata)
|
||||
for name, value in params.iteritems():
|
||||
if name and value:
|
||||
self.session.metadata.add_item(str(name), str(value))
|
||||
self.session.metadata.set_config(str(name), str(value))
|
||||
|
||||
def parse_session_config(self):
|
||||
session_config = xmlutils.get_first_child_by_tag_name(self.scenario, 'CORE:sessionconfig')
|
||||
|
|
|
@ -194,8 +194,7 @@ class CoreDocumentWriter0(Document):
|
|||
self.addaddresses(i, ifc)
|
||||
# per-interface models
|
||||
if netmodel and netmodel._name[:6] == "emane_":
|
||||
cfg = self.session.emane.getifcconfig(node.objid, netmodel._name,
|
||||
None, ifc)
|
||||
cfg = netmodel.getifcconfig(node.objid, ifc)
|
||||
if cfg:
|
||||
self.addmodels(i, ((netmodel, cfg),))
|
||||
|
||||
|
|
|
@ -654,8 +654,7 @@ class DeviceElement(NamedXmlElement):
|
|||
# per-interface models
|
||||
# XXX Remove???
|
||||
if netmodel and netmodel.name[:6] == "emane_":
|
||||
cfg = self.coreSession.emane.getifcconfig(device_object.objid, netmodel.name,
|
||||
None, interface_object)
|
||||
cfg = netmodel.getifcconfig(device_object.objid, interface_object)
|
||||
if cfg:
|
||||
interface_element.addModels(((netmodel, cfg),))
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ def example(options):
|
|||
|
||||
# create wlan network node
|
||||
wlan = session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
session.set_wireless_model(wlan, BasicRangeModel)
|
||||
wlan.setmodel(BasicRangeModel)
|
||||
|
||||
# create nodes
|
||||
wireless_nodes = []
|
||||
|
|
|
@ -214,6 +214,12 @@ def session():
|
|||
# return created session
|
||||
yield session_fixture
|
||||
|
||||
# clear session configurations
|
||||
session_fixture.location.reset()
|
||||
session_fixture.services.reset()
|
||||
session_fixture.mobility.config_reset()
|
||||
session_fixture.emane.config_reset()
|
||||
|
||||
# shutdown coreemu
|
||||
coreemu.shutdown()
|
||||
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
from random import shuffle
|
||||
|
||||
import pytest
|
||||
|
||||
from core.conf import ConfigurableManager
|
||||
from core.conf import ConfigurableOptions
|
||||
from core.conf import Configuration
|
||||
from core.enumerations import ConfigDataTypes
|
||||
|
@ -11,6 +6,7 @@ from core.enumerations import ConfigDataTypes
|
|||
class TestConfigurableOptions(ConfigurableOptions):
|
||||
name_one = "value1"
|
||||
name_two = "value2"
|
||||
configuration_maps = {}
|
||||
|
||||
@classmethod
|
||||
def configurations(cls):
|
||||
|
@ -47,7 +43,7 @@ class TestConf:
|
|||
|
||||
def test_nodes(self):
|
||||
# given
|
||||
config_manager = ConfigurableManager()
|
||||
config_manager = TestConfigurableOptions()
|
||||
test_config = {1: 2}
|
||||
node_id = 1
|
||||
config_manager.set_configs(test_config)
|
||||
|
@ -58,11 +54,11 @@ class TestConf:
|
|||
|
||||
# then
|
||||
assert len(nodes) == 1
|
||||
assert nodes[0] == node_id
|
||||
assert node_id in nodes
|
||||
|
||||
def test_config_reset_all(self):
|
||||
# given
|
||||
config_manager = ConfigurableManager()
|
||||
config_manager = TestConfigurableOptions()
|
||||
test_config = {1: 2}
|
||||
node_id = 1
|
||||
config_manager.set_configs(test_config)
|
||||
|
@ -72,11 +68,11 @@ class TestConf:
|
|||
config_manager.config_reset()
|
||||
|
||||
# then
|
||||
assert not config_manager._configuration_maps
|
||||
assert not config_manager.configuration_maps
|
||||
|
||||
def test_config_reset_node(self):
|
||||
# given
|
||||
config_manager = ConfigurableManager()
|
||||
config_manager = TestConfigurableOptions()
|
||||
test_config = {1: 2}
|
||||
node_id = 1
|
||||
config_manager.set_configs(test_config)
|
||||
|
@ -86,11 +82,12 @@ class TestConf:
|
|||
config_manager.config_reset(node_id)
|
||||
|
||||
# then
|
||||
assert not config_manager.get_configs(node_id)
|
||||
assert node_id not in config_manager.configuration_maps
|
||||
assert config_manager.get_configs()
|
||||
|
||||
def test_configs_setget(self):
|
||||
# given
|
||||
config_manager = ConfigurableManager()
|
||||
config_manager = TestConfigurableOptions()
|
||||
test_config = {1: 2}
|
||||
node_id = 1
|
||||
config_manager.set_configs(test_config)
|
||||
|
@ -106,7 +103,7 @@ class TestConf:
|
|||
|
||||
def test_config_setget(self):
|
||||
# given
|
||||
config_manager = ConfigurableManager()
|
||||
config_manager = TestConfigurableOptions()
|
||||
name = "test"
|
||||
value = "1"
|
||||
node_id = 1
|
||||
|
@ -120,56 +117,3 @@ class TestConf:
|
|||
# then
|
||||
assert defaults_value == value
|
||||
assert node_value == value
|
||||
|
||||
def test_all_configs(self):
|
||||
# given
|
||||
config_manager = ConfigurableManager()
|
||||
name = "test"
|
||||
value_one = "1"
|
||||
value_two = "2"
|
||||
node_id = 1
|
||||
config_one = "config1"
|
||||
config_two = "config2"
|
||||
config_manager.set_config(name, value_one, config_type=config_one)
|
||||
config_manager.set_config(name, value_two, config_type=config_two)
|
||||
config_manager.set_config(name, value_one, node_id=node_id, config_type=config_one)
|
||||
config_manager.set_config(name, value_two, node_id=node_id, config_type=config_two)
|
||||
|
||||
# when
|
||||
defaults_value_one = config_manager.get_config(name, config_type=config_one)
|
||||
defaults_value_two = config_manager.get_config(name, config_type=config_two)
|
||||
node_value_one = config_manager.get_config(name, node_id=node_id, config_type=config_one)
|
||||
node_value_two = config_manager.get_config(name, node_id=node_id, config_type=config_two)
|
||||
default_all_configs = config_manager.get_all_configs()
|
||||
node_all_configs = config_manager.get_all_configs(node_id=node_id)
|
||||
|
||||
# then
|
||||
assert defaults_value_one == value_one
|
||||
assert defaults_value_two == value_two
|
||||
assert node_value_one == value_one
|
||||
assert node_value_two == value_two
|
||||
assert len(default_all_configs) == 2
|
||||
assert config_one in default_all_configs
|
||||
assert config_two in default_all_configs
|
||||
assert len(node_all_configs) == 2
|
||||
assert config_one in node_all_configs
|
||||
assert config_two in node_all_configs
|
||||
|
||||
@pytest.mark.parametrize("_", xrange(10))
|
||||
def test_config_last_key(self, _):
|
||||
# given
|
||||
config_manager = ConfigurableManager()
|
||||
config = {1: 2}
|
||||
node_id = 1
|
||||
config_types = [1, 2, 3]
|
||||
shuffle(config_types)
|
||||
config_manager.set_configs(config, node_id=node_id, config_type=config_types[0])
|
||||
config_manager.set_configs(config, node_id=node_id, config_type=config_types[1])
|
||||
config_manager.set_configs(config, node_id=node_id, config_type=config_types[2])
|
||||
|
||||
# when
|
||||
keys = config_manager.get_all_configs(node_id=node_id).keys()
|
||||
|
||||
# then
|
||||
assert keys
|
||||
assert keys[-1] == config_types[2]
|
||||
|
|
|
@ -12,15 +12,17 @@ from mock import MagicMock
|
|||
|
||||
from core.emulator.emudata import NodeOptions
|
||||
from core.enumerations import MessageFlags, NodeTypes
|
||||
from core.mobility import BasicRangeModel
|
||||
from core.mobility import Ns2ScriptedMobility
|
||||
from core.mobility import BasicRangeModel, Ns2ScriptedMobility
|
||||
from core.netns.vnodeclient import VnodeClient
|
||||
from core.service import ServiceManager
|
||||
|
||||
_PATH = os.path.abspath(os.path.dirname(__file__))
|
||||
_SERVICES_PATH = os.path.join(_PATH, "myservices")
|
||||
_MOBILITY_FILE = os.path.join(_PATH, "mobility.scen")
|
||||
_XML_VERSIONS = ["0.0", "1.0"]
|
||||
_XML_VERSIONS = [
|
||||
"0.0",
|
||||
"1.0"
|
||||
]
|
||||
_WIRED = [
|
||||
NodeTypes.PEER_TO_PEER,
|
||||
NodeTypes.HUB,
|
||||
|
@ -101,7 +103,6 @@ class TestCore:
|
|||
:param str version: xml version to write and parse
|
||||
:param ip_prefixes: generates ip addresses for nodes
|
||||
"""
|
||||
|
||||
# create ptp
|
||||
ptp_node = session.add_node(_type=NodeTypes.PEER_TO_PEER)
|
||||
|
||||
|
@ -256,7 +257,7 @@ class TestCore:
|
|||
|
||||
# create wlan
|
||||
wlan_node = session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
session.set_wireless_model(wlan_node, BasicRangeModel)
|
||||
wlan_node.setmodel(BasicRangeModel)
|
||||
|
||||
# create nodes
|
||||
node_options = NodeOptions()
|
||||
|
@ -289,7 +290,7 @@ class TestCore:
|
|||
|
||||
# create wlan
|
||||
wlan_node = session.add_node(_type=NodeTypes.WIRELESS_LAN)
|
||||
session.set_wireless_model(wlan_node, BasicRangeModel)
|
||||
wlan_node.setmodel(BasicRangeModel)
|
||||
|
||||
# create nodes
|
||||
node_options = NodeOptions()
|
||||
|
@ -316,7 +317,7 @@ class TestCore:
|
|||
"script_pause": "",
|
||||
"script_stop": "",
|
||||
}
|
||||
session.mobility.set_configs(config, wlan_node.objid, Ns2ScriptedMobility.name)
|
||||
wlan_node.setmodel(Ns2ScriptedMobility, config)
|
||||
|
||||
# add handler for receiving node updates
|
||||
event = threading.Event()
|
||||
|
|
Loading…
Reference in a new issue