moved ConfigShim to being under tlv, updated RegisterTlvs to use enums directly in non tlv code

This commit is contained in:
Blake Harnden 2020-03-22 14:59:42 -07:00
parent 7a5a0f34ea
commit 39499a4ab4
14 changed files with 128 additions and 128 deletions

View file

@ -15,6 +15,7 @@ from queue import Empty, Queue
from core import utils
from core.api.tlv import coreapi, dataconversion, structutils
from core.api.tlv.dataconversion import ConfigShim
from core.api.tlv.enumerations import (
ConfigFlags,
ConfigTlvs,
@ -27,7 +28,6 @@ from core.api.tlv.enumerations import (
NodeTlvs,
SessionTlvs,
)
from core.config import ConfigShim
from core.emulator.data import ConfigData, EventData, ExceptionData, FileData
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
from core.emulator.enumerations import (
@ -398,7 +398,6 @@ class CoreHandler(socketserver.BaseRequestHandler):
logging.info(
"GUI has connected to session %d at %s", self.session.id, time.ctime()
)
tlv_data = b""
tlv_data += coreapi.CoreRegisterTlv.pack(
RegisterTlvs.EXECUTE_SERVER.value, "core-daemon"
@ -408,29 +407,29 @@ class CoreHandler(socketserver.BaseRequestHandler):
)
tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.UTILITY.value, "broker")
tlv_data += coreapi.CoreRegisterTlv.pack(
self.session.location.config_type, self.session.location.name
self.session.location.config_type.value, self.session.location.name
)
tlv_data += coreapi.CoreRegisterTlv.pack(
self.session.mobility.config_type, self.session.mobility.name
self.session.mobility.config_type.value, self.session.mobility.name
)
for model_name in self.session.mobility.models:
model_class = self.session.mobility.models[model_name]
tlv_data += coreapi.CoreRegisterTlv.pack(
model_class.config_type, model_class.name
model_class.config_type.value, model_class.name
)
tlv_data += coreapi.CoreRegisterTlv.pack(
self.session.services.config_type, self.session.services.name
self.session.services.config_type.value, self.session.services.name
)
tlv_data += coreapi.CoreRegisterTlv.pack(
self.session.emane.config_type, self.session.emane.name
self.session.emane.config_type.value, self.session.emane.name
)
for model_name in self.session.emane.models:
model_class = self.session.emane.models[model_name]
tlv_data += coreapi.CoreRegisterTlv.pack(
model_class.config_type, model_class.name
model_class.config_type.value, model_class.name
)
tlv_data += coreapi.CoreRegisterTlv.pack(
self.session.options.config_type, self.session.options.name
self.session.options.config_type.value, self.session.options.name
)
tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.UTILITY.value, "metadata")

View file

@ -1,9 +1,14 @@
"""
Converts CORE data objects into legacy API messages.
"""
import logging
from collections import OrderedDict
from typing import Dict, List
from core.api.tlv import coreapi, structutils
from core.api.tlv.enumerations import ConfigTlvs, NodeTlvs
from core.config import ConfigGroup, ConfigurableOptions
from core.emulator.data import ConfigData
def convert_node(node_data):
@ -67,3 +72,102 @@ def convert_config(config_data):
],
)
return coreapi.CoreConfMessage.pack(config_data.message_type, tlv_data)
class ConfigShim:
"""
Provides helper methods for converting newer configuration values into TLV
compatible formats.
"""
@classmethod
def str_to_dict(cls, key_values: str) -> Dict[str, str]:
"""
Converts a TLV key/value string into an ordered mapping.
:param key_values:
:return: ordered mapping of key/value pairs
"""
key_values = key_values.split("|")
values = OrderedDict()
for key_value in key_values:
key, value = key_value.split("=", 1)
values[key] = value
return values
@classmethod
def groups_to_str(cls, config_groups: List[ConfigGroup]) -> str:
"""
Converts configuration groups to a TLV formatted string.
:param config_groups: configuration groups to format
:return: TLV configuration group string
"""
group_strings = []
for config_group in config_groups:
group_string = (
f"{config_group.name}:{config_group.start}-{config_group.stop}"
)
group_strings.append(group_string)
return "|".join(group_strings)
@classmethod
def config_data(
cls,
flags: int,
node_id: int,
type_flags: int,
configurable_options: ConfigurableOptions,
config: Dict[str, str],
) -> ConfigData:
"""
Convert this class to a Config API message. Some TLVs are defined
by the class, but node number, conf type flags, and values must
be passed in.
:param flags: message flags
:param node_id: node id
:param type_flags: type flags
:param configurable_options: options to create config data for
:param config: configuration values for options
:return: configuration data object
"""
key_values = None
captions = None
data_types = []
possible_values = []
logging.debug("configurable: %s", configurable_options)
logging.debug("configuration options: %s", configurable_options.configurations)
logging.debug("configuration data: %s", config)
for configuration in configurable_options.configurations():
if not captions:
captions = configuration.label
else:
captions += f"|{configuration.label}"
data_types.append(configuration.type.value)
options = ",".join(configuration.options)
possible_values.append(options)
_id = configuration.id
config_value = config.get(_id, configuration.default)
key_value = f"{_id}={config_value}"
if not key_values:
key_values = key_value
else:
key_values += f"|{key_value}"
groups_str = cls.groups_to_str(configurable_options.config_groups())
return ConfigData(
message_type=flags,
node=node_id,
object=configurable_options.name,
type=type_flags,
data_types=tuple(data_types),
data_values=key_values,
captions=captions,
possible_values="|".join(possible_values),
bitmap=configurable_options.bitmap,
groups=groups_str,
)

View file

@ -7,7 +7,6 @@ from collections import OrderedDict
from typing import TYPE_CHECKING, Dict, List, Tuple, Type, Union
from core.emane.nodes import EmaneNet
from core.emulator.data import ConfigData
from core.emulator.enumerations import ConfigDataTypes
from core.nodes.network import WlanNode
@ -110,104 +109,6 @@ class ConfigurableOptions:
)
class ConfigShim:
"""
Provides helper methods for converting newer configuration values into TLV compatible formats.
"""
@classmethod
def str_to_dict(cls, key_values: str) -> Dict[str, str]:
"""
Converts a TLV key/value string into an ordered mapping.
:param key_values:
:return: ordered mapping of key/value pairs
"""
key_values = key_values.split("|")
values = OrderedDict()
for key_value in key_values:
key, value = key_value.split("=", 1)
values[key] = value
return values
@classmethod
def groups_to_str(cls, config_groups: List[ConfigGroup]) -> str:
"""
Converts configuration groups to a TLV formatted string.
:param config_groups: configuration groups to format
:return: TLV configuration group string
"""
group_strings = []
for config_group in config_groups:
group_string = (
f"{config_group.name}:{config_group.start}-{config_group.stop}"
)
group_strings.append(group_string)
return "|".join(group_strings)
@classmethod
def config_data(
cls,
flags: int,
node_id: int,
type_flags: int,
configurable_options: ConfigurableOptions,
config: Dict[str, str],
) -> ConfigData:
"""
Convert this class to a Config API message. Some TLVs are defined
by the class, but node number, conf type flags, and values must
be passed in.
:param flags: message flags
:param node_id: node id
:param type_flags: type flags
:param configurable_options: options to create config data for
:param config: configuration values for options
:return: configuration data object
"""
key_values = None
captions = None
data_types = []
possible_values = []
logging.debug("configurable: %s", configurable_options)
logging.debug("configuration options: %s", configurable_options.configurations)
logging.debug("configuration data: %s", config)
for configuration in configurable_options.configurations():
if not captions:
captions = configuration.label
else:
captions += f"|{configuration.label}"
data_types.append(configuration.type.value)
options = ",".join(configuration.options)
possible_values.append(options)
_id = configuration.id
config_value = config.get(_id, configuration.default)
key_value = f"{_id}={config_value}"
if not key_values:
key_values = key_value
else:
key_values += f"|{key_value}"
groups_str = cls.groups_to_str(configurable_options.config_groups())
return ConfigData(
message_type=flags,
node=node_id,
object=configurable_options.name,
type=type_flags,
data_types=tuple(data_types),
data_values=key_values,
captions=captions,
possible_values="|".join(possible_values),
bitmap=configurable_options.bitmap,
groups=groups_str,
)
class ConfigurableManager:
"""
Provides convenience methods for storing and retrieving configuration options for

View file

@ -60,7 +60,7 @@ class EmaneManager(ModelManager):
"""
name = "emane"
config_type = RegisterTlvs.EMULATION_SERVER.value
config_type = RegisterTlvs.EMULATION_SERVER
SUCCESS, NOT_NEEDED, NOT_READY = (0, 1, 2)
EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG"
DEFAULT_LOG_LEVEL = 3

View file

@ -103,12 +103,12 @@ class EmaneNet(CoreNetworkBase):
set the EmaneModel associated with this node
"""
logging.info("adding model: %s", model.name)
if model.config_type == RegisterTlvs.WIRELESS.value:
if model.config_type == RegisterTlvs.WIRELESS:
# EmaneModel really uses values from ConfigurableManager
# when buildnemxml() is called, not during init()
self.model = model(session=self.session, _id=self.id)
self.model.update_config(config)
elif model.config_type == RegisterTlvs.MOBILITY.value:
elif model.config_type == RegisterTlvs.MOBILITY:
self.mobility = model(session=self.session, _id=self.id)
self.mobility.update_config(config)

View file

@ -49,7 +49,6 @@ class LinkTypes(Enum):
WIRED = 1
# TODO: cleanup usage of .value
class RegisterTlvs(Enum):
"""
Register type, length, value enumerations.

View file

@ -1897,7 +1897,7 @@ class Session:
Return the current time we have been in the runtime state, or zero
if not in runtime.
"""
if self.state == EventTypes.RUNTIME_STATE.value:
if self.state == EventTypes.RUNTIME_STATE:
return time.monotonic() - self._state_time
else:
return 0.0

View file

@ -57,7 +57,7 @@ class SessionConfig(ConfigurableManager, ConfigurableOptions):
label="SDT3D URL",
),
]
config_type = RegisterTlvs.UTILITY.value
config_type = RegisterTlvs.UTILITY
def __init__(self) -> None:
super().__init__()

View file

@ -21,7 +21,7 @@ class GeoLocation:
"""
name = "location"
config_type = RegisterTlvs.UTILITY.value
config_type = RegisterTlvs.UTILITY
def __init__(self) -> None:
"""

View file

@ -36,7 +36,7 @@ class MobilityManager(ModelManager):
"""
name = "MobilityManager"
config_type = RegisterTlvs.WIRELESS.value
config_type = RegisterTlvs.WIRELESS
def __init__(self, session: "Session") -> None:
"""
@ -121,10 +121,7 @@ class MobilityManager(ModelManager):
logging.warning("Ignoring event for unknown model '%s'", model)
continue
if cls.config_type in [
RegisterTlvs.WIRELESS.value,
RegisterTlvs.MOBILITY.value,
]:
if cls.config_type in [RegisterTlvs.WIRELESS, RegisterTlvs.MOBILITY]:
model = node.mobility
else:
continue
@ -206,7 +203,7 @@ class WirelessModel(ConfigurableOptions):
Used for managing arbitrary configuration parameters.
"""
config_type = RegisterTlvs.WIRELESS.value
config_type = RegisterTlvs.WIRELESS
bitmap = None
position_callback = None
@ -575,7 +572,7 @@ class WayPointMobility(WirelessModel):
"""
name = "waypoint"
config_type = RegisterTlvs.MOBILITY.value
config_type = RegisterTlvs.MOBILITY
STATE_STOPPED = 0
STATE_RUNNING = 1

View file

@ -1090,13 +1090,13 @@ class WlanNode(CoreNetwork):
:return: nothing
"""
logging.debug("node(%s) setting model: %s", self.name, model.name)
if model.config_type == RegisterTlvs.WIRELESS.value:
if model.config_type == RegisterTlvs.WIRELESS:
self.model = model(session=self.session, _id=self.id)
for netif in self.netifs():
netif.poshook = self.model.position_callback
netif.setposition()
self.updatemodel(config)
elif model.config_type == RegisterTlvs.MOBILITY.value:
elif model.config_type == RegisterTlvs.MOBILITY:
self.mobility = model(session=self.session, _id=self.id)
self.mobility.update_config(config)

View file

@ -90,7 +90,7 @@ class Sdt:
self.address = (self.url.hostname, self.url.port)
self.protocol = self.url.scheme
def connect(self, flags: int = 0) -> bool:
def connect(self) -> bool:
"""
Connect to the SDT address/port if enabled.
@ -122,7 +122,7 @@ class Sdt:
self.connected = True
# refresh all objects in SDT3D when connecting after session start
if not flags & MessageFlags.ADD.value and not self.sendobjs():
if not self.sendobjs():
return False
return True

View file

@ -315,7 +315,7 @@ class CoreServices:
"""
name = "services"
config_type = RegisterTlvs.UTILITY.value
config_type = RegisterTlvs.UTILITY
def __init__(self, session: "Session") -> None:
"""

View file

@ -7,8 +7,8 @@ from mock import patch
from core.api.grpc import core_pb2
from core.api.grpc.client import CoreGrpcClient, InterfaceHelper
from core.api.tlv.dataconversion import ConfigShim
from core.api.tlv.enumerations import ConfigFlags
from core.config import ConfigShim
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emulator.data import EventData
from core.emulator.emudata import NodeOptions