daemon: removing python tlv related code and tests related to it

This commit is contained in:
Blake Harnden 2022-03-08 14:18:47 -08:00
parent dc7bb37252
commit c8a589ef76
29 changed files with 29 additions and 5439 deletions

View file

@ -1,9 +1,5 @@
#!/bin/sh
#
# (c)2010-2012 the Boeing Company
#
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
# Bootstrap the autoconf system.
#

View file

@ -1,8 +1,4 @@
# CORE
# (c)2010-2012 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
# Makefile for building netns components.
#

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,60 +0,0 @@
"""
Defines core server for handling TCP connections.
"""
import socketserver
from core.emulator.coreemu import CoreEmu
class CoreServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
"""
TCP server class, manages sessions and spawns request handlers for
incoming connections.
"""
daemon_threads = True
allow_reuse_address = True
def __init__(self, server_address, handler_class, config=None):
"""
Server class initialization takes configuration data and calls
the socketserver constructor.
:param tuple[str, int] server_address: server host and port to use
:param class handler_class: request handler
:param dict config: configuration setting
"""
self.coreemu = CoreEmu(config)
self.config = config
socketserver.TCPServer.__init__(self, server_address, handler_class)
class CoreUdpServer(socketserver.ThreadingMixIn, socketserver.UDPServer):
"""
UDP server class, manages sessions and spawns request handlers for
incoming connections.
"""
daemon_threads = True
allow_reuse_address = True
def __init__(self, server_address, handler_class, mainserver):
"""
Server class initialization takes configuration data and calls
the SocketServer constructor
:param server_address:
:param class handler_class: request handler
:param mainserver:
"""
self.mainserver = mainserver
socketserver.UDPServer.__init__(self, server_address, handler_class)
def start(self):
"""
Thread target to run concurrently with the TCP server.
:return: nothing
"""
self.serve_forever()

View file

@ -1,178 +0,0 @@
"""
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, NodeData
logger = logging.getLogger(__name__)
def convert_node(node_data: NodeData):
"""
Convenience method for converting NodeData to a packed TLV message.
:param core.emulator.data.NodeData node_data: node data to convert
:return: packed node message
"""
node = node_data.node
services = None
if node.services is not None:
services = "|".join([x.name for x in node.services])
server = None
if node.server is not None:
server = node.server.name
tlv_data = structutils.pack_values(
coreapi.CoreNodeTlv,
[
(NodeTlvs.NUMBER, node.id),
(NodeTlvs.TYPE, node.apitype.value),
(NodeTlvs.NAME, node.name),
(NodeTlvs.MODEL, node.type),
(NodeTlvs.EMULATION_SERVER, server),
(NodeTlvs.X_POSITION, int(node.position.x)),
(NodeTlvs.Y_POSITION, int(node.position.y)),
(NodeTlvs.CANVAS, node.canvas),
(NodeTlvs.SERVICES, services),
(NodeTlvs.LATITUDE, str(node.position.lat)),
(NodeTlvs.LONGITUDE, str(node.position.lon)),
(NodeTlvs.ALTITUDE, str(node.position.alt)),
(NodeTlvs.ICON, node.icon),
],
)
return coreapi.CoreNodeMessage.pack(node_data.message_type.value, tlv_data)
def convert_config(config_data):
"""
Convenience method for converting ConfigData to a packed TLV message.
:param core.emulator.data.ConfigData config_data: config data to convert
:return: packed message
"""
session = None
if config_data.session is not None:
session = str(config_data.session)
tlv_data = structutils.pack_values(
coreapi.CoreConfigTlv,
[
(ConfigTlvs.NODE, config_data.node),
(ConfigTlvs.OBJECT, config_data.object),
(ConfigTlvs.TYPE, config_data.type),
(ConfigTlvs.DATA_TYPES, config_data.data_types),
(ConfigTlvs.VALUES, config_data.data_values),
(ConfigTlvs.CAPTIONS, config_data.captions),
(ConfigTlvs.BITMAP, config_data.bitmap),
(ConfigTlvs.POSSIBLE_VALUES, config_data.possible_values),
(ConfigTlvs.GROUPS, config_data.groups),
(ConfigTlvs.SESSION, session),
(ConfigTlvs.IFACE_ID, config_data.iface_id),
(ConfigTlvs.NETWORK_ID, config_data.network_id),
(ConfigTlvs.OPAQUE, config_data.opaque),
],
)
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 = []
logger.debug("configurable: %s", configurable_options)
logger.debug("configuration options: %s", configurable_options.configurations)
logger.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

@ -1,212 +0,0 @@
"""
Enumerations specific to the CORE TLV API.
"""
from enum import Enum
CORE_API_PORT = 4038
class MessageTypes(Enum):
"""
CORE message types.
"""
NODE = 0x01
LINK = 0x02
EXECUTE = 0x03
REGISTER = 0x04
CONFIG = 0x05
FILE = 0x06
INTERFACE = 0x07
EVENT = 0x08
SESSION = 0x09
EXCEPTION = 0x0A
class NodeTlvs(Enum):
"""
Node type, length, value enumerations.
"""
NUMBER = 0x01
TYPE = 0x02
NAME = 0x03
IP_ADDRESS = 0x04
MAC_ADDRESS = 0x05
IP6_ADDRESS = 0x06
MODEL = 0x07
EMULATION_SERVER = 0x08
SESSION = 0x0A
X_POSITION = 0x20
Y_POSITION = 0x21
CANVAS = 0x22
EMULATION_ID = 0x23
NETWORK_ID = 0x24
SERVICES = 0x25
LATITUDE = 0x30
LONGITUDE = 0x31
ALTITUDE = 0x32
ICON = 0x42
OPAQUE = 0x50
class LinkTlvs(Enum):
"""
Link type, length, value enumerations.
"""
N1_NUMBER = 0x01
N2_NUMBER = 0x02
DELAY = 0x03
BANDWIDTH = 0x04
LOSS = 0x05
DUP = 0x06
JITTER = 0x07
MER = 0x08
BURST = 0x09
SESSION = 0x0A
MBURST = 0x10
TYPE = 0x20
GUI_ATTRIBUTES = 0x21
UNIDIRECTIONAL = 0x22
EMULATION_ID = 0x23
NETWORK_ID = 0x24
KEY = 0x25
IFACE1_NUMBER = 0x30
IFACE1_IP4 = 0x31
IFACE1_IP4_MASK = 0x32
IFACE1_MAC = 0x33
IFACE1_IP6 = 0x34
IFACE1_IP6_MASK = 0x35
IFACE2_NUMBER = 0x36
IFACE2_IP4 = 0x37
IFACE2_IP4_MASK = 0x38
IFACE2_MAC = 0x39
IFACE2_IP6 = 0x40
IFACE2_IP6_MASK = 0x41
IFACE1_NAME = 0x42
IFACE2_NAME = 0x43
OPAQUE = 0x50
class ExecuteTlvs(Enum):
"""
Execute type, length, value enumerations.
"""
NODE = 0x01
NUMBER = 0x02
TIME = 0x03
COMMAND = 0x04
RESULT = 0x05
STATUS = 0x06
SESSION = 0x0A
class ConfigTlvs(Enum):
"""
Configuration type, length, value enumerations.
"""
NODE = 0x01
OBJECT = 0x02
TYPE = 0x03
DATA_TYPES = 0x04
VALUES = 0x05
CAPTIONS = 0x06
BITMAP = 0x07
POSSIBLE_VALUES = 0x08
GROUPS = 0x09
SESSION = 0x0A
IFACE_ID = 0x0B
NETWORK_ID = 0x24
OPAQUE = 0x50
class ConfigFlags(Enum):
"""
Configuration flags.
"""
NONE = 0x00
REQUEST = 0x01
UPDATE = 0x02
RESET = 0x03
class FileTlvs(Enum):
"""
File type, length, value enumerations.
"""
NODE = 0x01
NAME = 0x02
MODE = 0x03
NUMBER = 0x04
TYPE = 0x05
SOURCE_NAME = 0x06
SESSION = 0x0A
DATA = 0x10
COMPRESSED_DATA = 0x11
class InterfaceTlvs(Enum):
"""
Interface type, length, value enumerations.
"""
NODE = 0x01
NUMBER = 0x02
NAME = 0x03
IP_ADDRESS = 0x04
MASK = 0x05
MAC_ADDRESS = 0x06
IP6_ADDRESS = 0x07
IP6_MASK = 0x08
TYPE = 0x09
SESSION = 0x0A
STATE = 0x0B
EMULATION_ID = 0x23
NETWORK_ID = 0x24
class EventTlvs(Enum):
"""
Event type, length, value enumerations.
"""
NODE = 0x01
TYPE = 0x02
NAME = 0x03
DATA = 0x04
TIME = 0x05
SESSION = 0x0A
class SessionTlvs(Enum):
"""
Session type, length, value enumerations.
"""
NUMBER = 0x01
NAME = 0x02
FILE = 0x03
NODE_COUNT = 0x04
DATE = 0x05
THUMB = 0x06
USER = 0x07
OPAQUE = 0x0A
class ExceptionTlvs(Enum):
"""
Exception type, length, value enumerations.
"""
NODE = 0x01
SESSION = 0x02
LEVEL = 0x03
SOURCE = 0x04
DATE = 0x05
TEXT = 0x06
OPAQUE = 0x0A

View file

@ -1,45 +0,0 @@
"""
Utilities for working with python struct data.
"""
import logging
logger = logging.getLogger(__name__)
def pack_values(clazz, packers):
"""
Pack values for a given legacy class.
:param class clazz: class that will provide a pack method
:param list packers: a list of tuples that are used to pack values and transform them
:return: packed data string of all values
"""
# iterate through tuples of values to pack
logger.debug("packing: %s", packers)
data = b""
for packer in packers:
# check if a transformer was provided for valid values
transformer = None
if len(packer) == 2:
tlv_type, value = packer
elif len(packer) == 3:
tlv_type, value, transformer = packer
else:
raise RuntimeError("packer had more than 3 arguments")
# only pack actual values and avoid packing empty strings
# protobuf defaults to empty strings and does no imply a value to set
if value is None or (isinstance(value, str) and not value):
continue
# transform values as needed
if transformer:
value = transformer(value)
# pack and add to existing data
logger.debug("packing: %s - %s type(%s)", tlv_type, value, type(value))
data += clazz.pack(tlv_type.value, value)
return data

View file

@ -20,6 +20,17 @@ class MessageFlags(Enum):
TTY = 0x40
class ConfigFlags(Enum):
"""
Configuration flags.
"""
NONE = 0x00
REQUEST = 0x01
UPDATE = 0x02
RESET = 0x03
class NodeTypes(Enum):
"""
Node types.

View file

@ -1007,15 +1007,14 @@ class Session:
env["SESSION_STATE"] = str(self.state)
# try reading and merging optional environments from:
# /etc/core/environment
# /home/user/.core/environment
# /home/user/.coregui/environment
# /tmp/pycore.<session id>/environment
core_env_path = constants.CORE_CONF_DIR / "environment"
session_env_path = self.directory / "environment"
if self.user:
user_home_path = Path(f"~{self.user}").expanduser()
user_env1 = user_home_path / ".core" / "environment"
user_env2 = user_home_path / ".coregui" / "environment"
paths = [core_env_path, user_env1, user_env2, session_env_path]
user_env = user_home_path / ".coregui" / "environment"
paths = [core_env_path, user_env, session_env_path]
else:
paths = [core_env_path, session_env_path]
for path in paths:

View file

@ -716,8 +716,7 @@ class PtpNet(CoreNetwork):
def links(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]:
"""
Build CORE API TLVs for a point-to-point link. One Link message
describes this network.
Get peer to peer link.
:param flags: message flags
:return: list of link data

View file

@ -109,114 +109,6 @@ class ServiceDependencies:
return self.boot_paths
class ServiceShim:
keys: List[str] = [
"dirs",
"files",
"startidx",
"cmdup",
"cmddown",
"cmdval",
"meta",
"starttime",
]
@classmethod
def tovaluelist(cls, node: CoreNode, service: "CoreService") -> str:
"""
Convert service properties into a string list of key=value pairs,
separated by "|".
:param node: node to get value list for
:param service: service to get value list for
:return: value list string
"""
start_time = 0
start_index = 0
valmap = [
service.dirs,
service.configs,
start_index,
service.startup,
service.shutdown,
service.validate,
service.meta,
start_time,
]
if not service.custom:
valmap[1] = service.get_configs(node)
valmap[3] = service.get_startup(node)
vals = ["%s=%s" % (x, y) for x, y in zip(cls.keys, valmap)]
return "|".join(vals)
@classmethod
def fromvaluelist(cls, service: "CoreService", values: List[str]) -> None:
"""
Convert list of values into properties for this instantiated
(customized) service.
:param service: service to get value list for
:param values: value list to set properties from
:return: nothing
"""
# TODO: support empty value? e.g. override default meta with ''
for key in cls.keys:
try:
cls.setvalue(service, key, values[cls.keys.index(key)])
except IndexError:
# old config does not need to have new keys
logger.exception("error indexing into key")
@classmethod
def setvalue(cls, service: "CoreService", key: str, value: str) -> None:
"""
Set values for this service.
:param service: service to get value list for
:param key: key to set value for
:param value: value of key to set
:return: nothing
"""
if key not in cls.keys:
raise ValueError("key `%s` not in `%s`" % (key, cls.keys))
# this handles data conversion to int, string, and tuples
if value:
if key == "startidx":
value = int(value)
elif key == "starttime":
value = float(value)
elif key == "meta":
value = str(value)
else:
value = utils.make_tuple_fromstr(value, str)
if key == "dirs":
service.dirs = value
elif key == "files":
service.configs = value
elif key == "cmdup":
service.startup = value
elif key == "cmddown":
service.shutdown = value
elif key == "cmdval":
service.validate = value
elif key == "meta":
service.meta = value
@classmethod
def servicesfromopaque(cls, opaque: str) -> List[str]:
"""
Build a list of services from an opaque data string.
:param opaque: opaque data string
:return: services
"""
servicesstring = opaque.split(":")
if servicesstring[0] != "service":
return []
return servicesstring[1].split(",")
class ServiceManager:
"""
Manages services available for CORE nodes to use.

View file

@ -1,7 +1,5 @@
[core-daemon]
#distributed_address = 127.0.0.1
listenaddr = localhost
port = 4038
grpcaddress = localhost
grpcport = 50051
quagga_bin_search = "/usr/local/bin /usr/bin /usr/lib/quagga"

View file

@ -1,8 +1,4 @@
# CORE
# (c)2012 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
# Builds html and pdf documentation using Sphinx.
#

View file

@ -8,19 +8,15 @@ message handlers are defined and some support for sending messages.
import argparse
import logging
import os
import sys
import threading
import time
from configparser import ConfigParser
from pathlib import Path
from core import constants
from core.api.grpc.server import CoreGrpcServer
from core.api.tlv.corehandlers import CoreHandler, CoreUdpHandler
from core.api.tlv.coreserver import CoreServer, CoreUdpServer
from core.api.tlv.enumerations import CORE_API_PORT
from core.constants import CORE_CONF_DIR, COREDPY_VERSION
from core.utils import close_onexec, load_logging_config
from core.emulator.coreemu import CoreEmu
from core.utils import load_logging_config
logger = logging.getLogger(__name__)
@ -34,20 +30,6 @@ def banner():
logger.info("CORE daemon v.%s started %s", constants.COREDPY_VERSION, time.ctime())
def start_udp(mainserver, server_address):
"""
Start a thread running a UDP server on the same host,port for
connectionless requests.
:param CoreServer mainserver: main core tcp server to piggy back off of
:param server_address:
:return: CoreUdpServer
"""
mainserver.udpserver = CoreUdpServer(server_address, CoreUdpHandler, mainserver)
mainserver.udpthread = threading.Thread(target=mainserver.udpserver.start, daemon=True)
mainserver.udpthread.start()
def cored(cfg):
"""
Start the CoreServer object and enter the server loop.
@ -55,34 +37,13 @@ def cored(cfg):
:param dict cfg: core configuration
:return: nothing
"""
host = cfg["listenaddr"]
port = int(cfg["port"])
if host == "" or host is None:
host = "localhost"
try:
address = (host, port)
server = CoreServer(address, CoreHandler, cfg)
except:
logger.exception("error starting main server on: %s:%s", host, port)
sys.exit(1)
# initialize grpc api
grpc_server = CoreGrpcServer(server.coreemu)
coreemu = CoreEmu(cfg)
grpc_server = CoreGrpcServer(coreemu)
address_config = cfg["grpcaddress"]
port_config = cfg["grpcport"]
grpc_address = f"{address_config}:{port_config}"
grpc_thread = threading.Thread(target=grpc_server.listen, args=(grpc_address,), daemon=True)
grpc_thread.start()
# start udp server
start_udp(server, address)
# close handlers
close_onexec(server.fileno())
logger.info("CORE TLV API TCP/UDP listening on: %s:%s", host, port)
server.serve_forever()
grpc_server.listen(grpc_address)
def get_merged_config(filename):
@ -98,49 +59,38 @@ def get_merged_config(filename):
default_grpc_port = "50051"
default_address = "localhost"
defaults = {
"port": str(CORE_API_PORT),
"listenaddr": default_address,
"grpcport": default_grpc_port,
"grpcaddress": default_address,
"logfile": default_log
}
parser = argparse.ArgumentParser(
description=f"CORE daemon v.{COREDPY_VERSION} instantiates Linux network namespace nodes.")
parser.add_argument("-f", "--configfile", dest="configfile",
help=f"read config from specified file; default = {filename}")
parser.add_argument("-p", "--port", dest="port", type=int,
help=f"port number to listen on; default = {CORE_API_PORT}")
parser.add_argument("--ovs", action="store_true", help="enable experimental ovs mode, default is false")
parser.add_argument("--grpc-port", dest="grpcport",
help=f"grpc port to listen on; default {default_grpc_port}")
parser.add_argument("--grpc-address", dest="grpcaddress",
help=f"grpc address to listen on; default {default_address}")
parser.add_argument("-l", "--logfile", help=f"core logging configuration; default {default_log}")
# parse command line options
args = parser.parse_args()
# convert ovs to internal format
args.ovs = "1" if args.ovs else "0"
# read the config file
if args.configfile is not None:
filename = args.configfile
del args.configfile
cfg = ConfigParser(defaults)
cfg.read(filename)
section = "core-daemon"
if not cfg.has_section(section):
cfg.add_section(section)
# merge argparse with configparser
for opt in vars(args):
val = getattr(args, opt)
if val is not None:
cfg.set(section, opt, str(val))
return dict(cfg.items(section))

View file

@ -1,70 +0,0 @@
#!/usr/bin/env python3
import argparse
import re
import sys
from pathlib import Path
from core import utils
from core.api.grpc.client import CoreGrpcClient
from core.errors import CoreCommandError
if __name__ == "__main__":
# parse flags
parser = argparse.ArgumentParser(description="Converts CORE imn files to xml")
parser.add_argument("-f", "--file", dest="file", help="imn file to convert")
parser.add_argument(
"-d", "--dest", dest="dest", default=None, help="destination for xml file, defaults to same location as imn"
)
args = parser.parse_args()
# validate provided file exists
imn_file = Path(args.file)
if not imn_file.exists():
print(f"{args.file} does not exist")
sys.exit(1)
# validate destination
if args.dest is not None:
dest = Path(args.dest)
if not dest.exists() or not dest.is_dir():
print(f"{dest.resolve()} does not exist or is not a directory")
sys.exit(1)
xml_file = Path(dest, imn_file.with_suffix(".xml").name)
else:
xml_file = Path(imn_file.with_suffix(".xml").name)
# validate xml file
if xml_file.exists():
print(f"{xml_file.resolve()} already exists")
sys.exit(1)
# run provided imn using core-gui batch mode
try:
print(f"running {imn_file.resolve()} in batch mode")
output = utils.cmd(f"core-gui --batch {imn_file.resolve()}")
last_line = output.split("\n")[-1].strip()
# check for active session
if last_line == "Another session is active.":
print("need to restart core-daemon or shutdown previous batch session")
sys.exit(1)
# parse session id
m = re.search(r"Session id is (\d+)\.", last_line)
if not m:
print(f"failed to find session id: {output}")
sys.exit(1)
session_id = int(m.group(1))
print(f"created session {session_id}")
# save xml and delete session
client = CoreGrpcClient()
with client.context_connect():
print(f"saving xml {xml_file.resolve()}")
client.save_xml(session_id, str(xml_file))
print(f"deleting session {session_id}")
client.delete_session(session_id)
except CoreCommandError as e:
print(f"core-gui batch failed for {imn_file.resolve()}: {e}")
sys.exit(1)

View file

@ -1,247 +0,0 @@
#!/usr/bin/env python3
"""
core-manage: Helper tool to add, remove, or check for services, models, and
node types in a CORE installation.
"""
import ast
import optparse
import os
import re
import sys
from core import services
from core.constants import CORE_CONF_DIR
class FileUpdater:
"""
Helper class for changing configuration files.
"""
actions = ("add", "remove", "check")
targets = ("service", "model", "nodetype")
def __init__(self, action, target, data, options):
"""
"""
self.action = action
self.target = target
self.data = data
self.options = options
self.verbose = options.verbose
self.search, self.filename = self.get_filename(target)
def process(self):
""" Invoke update_file() using a helper method depending on target.
"""
if self.verbose:
txt = "Updating"
if self.action == "check":
txt = "Checking"
sys.stdout.write(f"{txt} file: {self.filename}\n")
if self.target == "service":
r = self.update_file(fn=self.update_services)
elif self.target == "model":
r = self.update_file(fn=self.update_emane_models)
elif self.target == "nodetype":
r = self.update_nodes_conf()
if self.verbose:
txt = ""
if not r:
txt = "NOT "
if self.action == "check":
sys.stdout.write(f"String {txt} found.\n")
else:
sys.stdout.write(f"File {txt} updated.\n")
return r
def update_services(self, line):
""" Modify the __init__.py file having this format:
__all__ = ["quagga", "nrl", "xorp", "bird", ]
Returns True or False when "check" is the action, a modified line
otherwise.
"""
line = line.strip("\n")
key, valstr = line.split("= ")
vals = ast.literal_eval(valstr)
r = self.update_keyvals(key, vals)
if self.action == "check":
return r
valstr = str(r)
return "= ".join([key, valstr]) + "\n"
def update_emane_models(self, line):
""" Modify the core.conf file having this format:
emane_models = RfPipe, Ieee80211abg, CommEffect, Bypass
Returns True or False when "check" is the action, a modified line
otherwise.
"""
line = line.strip("\n")
key, valstr = line.split("= ")
vals = valstr.split(", ")
r = self.update_keyvals(key, vals)
if self.action == "check":
return r
valstr = ", ".join(r)
return "= ".join([key, valstr]) + "\n"
def update_keyvals(self, key, vals):
""" Perform self.action on (key, vals).
Returns True or False when "check" is the action, a modified line
otherwise.
"""
if self.action == "check":
if self.data in vals:
return True
else:
return False
elif self.action == "add":
if self.data not in vals:
vals.append(self.data)
elif self.action == "remove":
try:
vals.remove(self.data)
except ValueError:
pass
return vals
def get_filename(self, target):
""" Return search string and filename based on target.
"""
if target == "service":
filename = os.path.abspath(services.__file__)
search = "__all__ ="
elif target == "model":
filename = os.path.join(CORE_CONF_DIR, "core.conf")
search = "emane_models ="
elif target == "nodetype":
if self.options.userpath is None:
raise ValueError("missing user path")
filename = os.path.join(self.options.userpath, "nodes.conf")
search = self.data
else:
raise ValueError("unknown target")
if not os.path.exists(filename):
raise ValueError(f"file {filename} does not exist")
return search, filename
def update_file(self, fn=None):
""" Open a file and search for self.search, invoking the supplied
function on the matching line. Write file changes if necessary.
Returns True if the file has changed (or action is "check" and the
search string is found), False otherwise.
"""
changed = False
output = "" # this accumulates output, assumes input is small
with open(self.filename, "r") as f:
for line in f:
if line[:len(self.search)] == self.search:
r = fn(line) # line may be modified by fn() here
if self.action == "check":
return r
else:
if line != r:
changed = True
line = r
output += line
if changed:
with open(self.filename, "w") as f:
f.write(output)
return changed
def update_nodes_conf(self):
""" Add/remove/check entries from nodes.conf. This file
contains a Tcl-formatted array of node types. The array index must be
properly set for new entries. Uses self.{action, filename, search,
data} variables as input and returns the same value as update_file().
"""
changed = False
output = "" # this accumulates output, assumes input is small
with open(self.filename, "r") as f:
for line in f:
# make sure data is not added twice
if line.find(self.search) >= 0:
if self.action == "check":
return True
elif self.action == "add":
return False
elif self.action == "remove":
changed = True
continue
else:
output += line
if self.action == "add":
index = int(re.match("^\d+", line).group(0))
output += str(index + 1) + " " + self.data + "\n"
changed = True
if changed:
with open(self.filename, "w") as f:
f.write(output)
return changed
def main():
actions = ", ".join(FileUpdater.actions)
targets = ", ".join(FileUpdater.targets)
usagestr = "usage: %prog [-h] [options] <action> <target> <string>\n"
usagestr += "\nHelper tool to add, remove, or check for "
usagestr += "services, models, and node types\nin a CORE installation.\n"
usagestr += "\nExamples:\n %prog add service newrouting"
usagestr += "\n %prog -v check model RfPipe"
usagestr += "\n %prog --userpath=\"$HOME/.core\" add nodetype \"{ftp ftp.gif ftp.gif {DefaultRoute FTP} netns {FTP server} }\" \n"
usagestr += f"\nArguments:\n <action> should be one of: {actions}"
usagestr += f"\n <target> should be one of: {targets}"
usagestr += f"\n <string> is the text to {actions}"
parser = optparse.OptionParser(usage=usagestr)
parser.set_defaults(userpath=None, verbose=False, )
parser.add_option("--userpath", dest="userpath", type="string",
help="use the specified user path (e.g. \"$HOME/.core" \
"\") to access nodes.conf")
parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
help="be verbose when performing action")
def usage(msg=None, err=0):
sys.stdout.write("\n")
if msg:
sys.stdout.write(msg + "\n\n")
parser.print_help()
sys.exit(err)
(options, args) = parser.parse_args()
if len(args) != 3:
usage("Missing required arguments!", 1)
action = args[0]
if action not in FileUpdater.actions:
usage(f"invalid action {action}", 1)
target = args[1]
if target not in FileUpdater.targets:
usage(f"invalid target {target}", 1)
if target == "nodetype" and not options.userpath:
usage(f"user path option required for this target ({target})")
data = args[2]
try:
up = FileUpdater(action, target, data, options)
r = up.process()
except Exception as e:
sys.stderr.write(f"Exception: {e}\n")
sys.exit(1)
if not r:
sys.exit(1)
sys.exit(0)
if __name__ == "__main__":
main()

View file

@ -1,279 +0,0 @@
#!/usr/bin/env python3
"""
coresendmsg: utility for generating CORE messages
"""
import optparse
import os
import socket
import sys
from core.api.tlv import coreapi
from core.api.tlv.enumerations import CORE_API_PORT, MessageTypes, SessionTlvs
from core.emulator.enumerations import MessageFlags
def print_available_tlvs(t, tlv_class):
"""
Print a TLV list.
"""
print(f"TLVs available for {t} message:")
for tlv in sorted([tlv for tlv in tlv_class.tlv_type_map], key=lambda x: x.name):
print(tlv.name.lower())
def print_examples(name):
"""
Print example usage of this script.
"""
examples = [
("node number=3 x_position=125 y_position=525",
"move node number 3 to x,y=(125,525)"),
("node number=4 icon=/usr/local/share/core/icons/normal/router_red.gif",
"change node number 4\"s icon to red"),
("node flags=add number=5 type=0 name=\"n5\" x_position=500 y_position=500",
"add a new router node n5"),
("link n1_number=2 n2_number=3 delay=15000",
"set a 15ms delay on the link between n2 and n3"),
("link n1_number=2 n2_number=3 gui_attributes=\"color=blue\"",
"change the color of the link between n2 and n3"),
("link flags=add n1_number=4 n2_number=5 interface1_ip4=\"10.0.3.2\" "
"interface1_ip4_mask=24 interface2_ip4=\"10.0.3.1\" interface2_ip4_mask=24",
"link node n5 with n4 using the given interface addresses"),
("execute flags=string,text node=1 number=1000 command=\"uname -a\" -l",
"run a command on node 1 and wait for the result"),
("execute node=2 number=1001 command=\"killall ospfd\"",
"run a command on node 2 and ignore the result"),
("file flags=add node=1 name=\"/var/log/test.log\" data=\"hello world.\"",
"write a test.log file on node 1 with the given contents"),
("file flags=add node=2 name=\"test.log\" source_name=\"./test.log\"",
"move a test.log file from host to node 2"),
]
print(f"Example {name} invocations:")
for cmd, descr in examples:
print(f" {name} {cmd}\n\t\t{descr}")
def receive_message(sock):
"""
Retrieve a message from a socket and return the CoreMessage object or
None upon disconnect. Socket data beyond the first message is dropped.
"""
try:
# large receive buffer used for UDP sockets, instead of just receiving
# the 4-byte header
data = sock.recv(4096)
msghdr = data[:coreapi.CoreMessage.header_len]
except KeyboardInterrupt:
print("CTRL+C pressed")
sys.exit(1)
if len(msghdr) == 0:
return None
msgdata = None
msgtype, msgflags, msglen = coreapi.CoreMessage.unpack_header(msghdr)
if msglen:
msgdata = data[coreapi.CoreMessage.header_len:]
try:
msgcls = coreapi.CLASS_MAP[msgtype]
except KeyError:
msg = coreapi.CoreMessage(msgflags, msghdr, msgdata)
msg.message_type = msgtype
print(f"unimplemented CORE message type: {msg.type_str()}")
return msg
if len(data) > msglen + coreapi.CoreMessage.header_len:
data_size = len(data) - (msglen + coreapi.CoreMessage.header_len)
print(f"received a message of type {msgtype}, dropping {data_size} bytes of extra data")
return msgcls(msgflags, msghdr, msgdata)
def connect_to_session(sock, requested):
"""
Use Session Messages to retrieve the current list of sessions and
connect to the first one.
"""
# request the session list
tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, "")
flags = MessageFlags.STRING.value
smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata)
sock.sendall(smsg)
print("waiting for session list...")
smsgreply = receive_message(sock)
if smsgreply is None:
print("disconnected")
return False
sessstr = smsgreply.get_tlv(SessionTlvs.NUMBER.value)
if sessstr is None:
print("missing session numbers")
return False
# join the first session (that is not our own connection)
tmp, localport = sock.getsockname()
sessions = sessstr.split("|")
sessions.remove(str(localport))
if len(sessions) == 0:
print("no sessions to join")
return False
if not requested:
session = sessions[0]
elif requested in sessions:
session = requested
else:
print("requested session not found!")
return False
print(f"joining session: {session}")
tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, session)
flags = MessageFlags.ADD.value
smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata)
sock.sendall(smsg)
return True
def receive_response(sock, opt):
"""
Receive and print a CORE message from the given socket.
"""
print("waiting for response...")
msg = receive_message(sock)
if msg is None:
print(f"disconnected from {opt.address}:{opt.port}")
sys.exit(0)
print(f"received message: {msg}")
def main():
"""
Parse command-line arguments to build and send a CORE message.
"""
types = [message_type.name.lower() for message_type in MessageTypes]
flags = [flag.name.lower() for flag in MessageFlags]
types_usage = " ".join(types)
flags_usage = " ".join(flags)
usagestr = (
"usage: %prog [-h|-H] [options] [message-type] [flags=flags] "
"[message-TLVs]\n\n"
f"Supported message types:\n {types_usage}\n"
f"Supported message flags (flags=f1,f2,...):\n {flags_usage}"
)
parser = optparse.OptionParser(usage=usagestr)
default_address = "localhost"
default_session = None
default_tcp = False
parser.set_defaults(
port=CORE_API_PORT,
address=default_address,
session=default_session,
listen=False,
examples=False,
tlvs=False,
tcp=default_tcp
)
parser.add_option("-H", dest="examples", action="store_true",
help="show example usage help message and exit")
parser.add_option("-p", "--port", dest="port", type=int,
help=f"TCP port to connect to, default: {CORE_API_PORT}")
parser.add_option("-a", "--address", dest="address", type=str,
help=f"Address to connect to, default: {default_address}")
parser.add_option("-s", "--session", dest="session", type=str,
help=f"Session to join, default: {default_session}")
parser.add_option("-l", "--listen", dest="listen", action="store_true",
help="Listen for a response message and print it.")
parser.add_option("-t", "--list-tlvs", dest="tlvs", action="store_true",
help="List TLVs for the specified message type.")
parser.add_option("--tcp", dest="tcp", action="store_true",
help=f"Use TCP instead of UDP and connect to a session default: {default_tcp}")
def usage(msg=None, err=0):
print()
if msg:
print(f"{msg}\n")
parser.print_help()
sys.exit(err)
# parse command line opt
opt, args = parser.parse_args()
if opt.examples:
print_examples(os.path.basename(sys.argv[0]))
sys.exit(0)
if len(args) == 0:
usage("Please specify a message type to send.")
# given a message type t, determine the message and TLV classes
t = args.pop(0)
t = t.lower()
if t not in types:
usage(f"Unknown message type requested: {t}")
message_type = MessageTypes[t.upper()]
msg_cls = coreapi.CLASS_MAP[message_type.value]
tlv_cls = msg_cls.tlv_class
# list TLV types for this message type
if opt.tlvs:
print_available_tlvs(t, tlv_cls)
sys.exit(0)
# build a message consisting of TLVs from "type=value" arguments
flagstr = ""
tlvdata = b""
for a in args:
typevalue = a.split("=")
if len(typevalue) < 2:
usage(f"Use \"type=value\" syntax instead of \"{a}\".")
tlv_typestr = typevalue[0].lower()
tlv_valstr = "=".join(typevalue[1:])
if tlv_typestr == "flags":
flagstr = tlv_valstr
continue
try:
tlv_type = tlv_cls.tlv_type_map[tlv_typestr.upper()]
tlvdata += tlv_cls.pack_string(tlv_type.value, tlv_valstr)
except KeyError:
usage(f"Unknown TLV: \"{tlv_typestr}\"")
flags = 0
for f in flagstr.split(","):
if f == "":
continue
try:
flag_enum = MessageFlags[f.upper()]
n = flag_enum.value
flags |= n
except KeyError:
usage(f"Invalid flag \"{f}\".")
msg = msg_cls.pack(flags, tlvdata)
if opt.tcp:
protocol = socket.SOCK_STREAM
else:
protocol = socket.SOCK_DGRAM
sock = socket.socket(socket.AF_INET, protocol)
sock.setblocking(True)
try:
sock.connect((opt.address, opt.port))
except Exception as e:
print(f"Error connecting to {opt.address}:{opt.port}:\n\t{e}")
sys.exit(1)
if opt.tcp and not connect_to_session(sock, opt.session):
print("warning: continuing without joining a session!")
sock.sendall(msg)
if opt.listen:
receive_response(sock, opt)
if opt.tcp:
sock.shutdown(socket.SHUT_RDWR)
sock.close()
sys.exit(0)
if __name__ == "__main__":
main()

View file

@ -7,11 +7,9 @@ import time
import mock
import pytest
from mock.mock import MagicMock
from core.api.grpc.client import InterfaceHelper
from core.api.grpc.server import CoreGrpcServer
from core.api.tlv.corehandlers import CoreHandler
from core.emulator.coreemu import CoreEmu
from core.emulator.data import IpPrefixes
from core.emulator.distributed import DistributedServer
@ -104,17 +102,6 @@ def module_grpc(global_coreemu):
grpc_server.server.stop(None)
@pytest.fixture(scope="module")
def module_coretlv(patcher, global_coreemu, global_session):
request_mock = MagicMock()
request_mock.fileno = MagicMock(return_value=1)
server = MockServer(global_coreemu)
request_handler = CoreHandler(request_mock, "", server)
request_handler.session = global_session
request_handler.add_session_handlers()
yield request_handler
@pytest.fixture
def grpc_server(module_grpc):
yield module_grpc
@ -130,16 +117,6 @@ def session(global_session):
global_session.clear()
@pytest.fixture
def coretlv(module_coretlv):
session = module_coretlv.session
session.set_state(EventTypes.CONFIGURATION_STATE)
coreemu = module_coretlv.coreemu
coreemu.sessions[session.id] = session
yield module_coretlv
coreemu.shutdown()
def pytest_addoption(parser):
parser.addoption("--distributed", help="distributed server address")
parser.addoption("--mock", action="store_true", help="run without mocking")

View file

@ -31,8 +31,6 @@ from core.api.grpc.wrappers import (
SessionLocation,
SessionState,
)
from core.api.tlv.dataconversion import ConfigShim
from core.api.tlv.enumerations import ConfigFlags
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet
from core.emulator.data import EventData, IpPrefixes, NodeData, NodeOptions
@ -820,30 +818,6 @@ class TestGrpc:
# then
queue.get(timeout=5)
def test_config_events(self, grpc_server: CoreGrpcServer):
# given
client = CoreGrpcClient()
session = grpc_server.coreemu.create_session()
queue = Queue()
def handle_event(event: Event) -> None:
assert event.session_id == session.id
assert event.config_event is not None
queue.put(event)
# then
with client.context_connect():
client.events(session.id, handle_event)
time.sleep(0.1)
session_config = session.options.get_configs()
config_data = ConfigShim.config_data(
0, None, ConfigFlags.UPDATE.value, session.options, session_config
)
session.broadcast_config(config_data)
# then
queue.get(timeout=5)
def test_exception_events(self, grpc_server: CoreGrpcServer):
# given
client = CoreGrpcClient()

View file

@ -1,941 +0,0 @@
"""
Tests for testing tlv message handling.
"""
import time
from pathlib import Path
from typing import Optional
import mock
import netaddr
import pytest
from mock import MagicMock
from core.api.tlv import coreapi
from core.api.tlv.corehandlers import CoreHandler
from core.api.tlv.enumerations import (
ConfigFlags,
ConfigTlvs,
EventTlvs,
ExecuteTlvs,
FileTlvs,
LinkTlvs,
NodeTlvs,
SessionTlvs,
)
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emulator.enumerations import EventTypes, MessageFlags, NodeTypes, RegisterTlvs
from core.errors import CoreError
from core.location.mobility import BasicRangeModel
from core.nodes.base import CoreNode, NodeBase
from core.nodes.network import SwitchNode, WlanNode
def dict_to_str(values) -> str:
return "|".join(f"{x}={values[x]}" for x in values)
class TestGui:
@pytest.mark.parametrize(
"node_type, model",
[
(NodeTypes.DEFAULT, "PC"),
(NodeTypes.EMANE, None),
(NodeTypes.HUB, None),
(NodeTypes.SWITCH, None),
(NodeTypes.WIRELESS_LAN, None),
(NodeTypes.TUNNEL, None),
],
)
def test_node_add(
self, coretlv: CoreHandler, node_type: NodeTypes, model: Optional[str]
):
node_id = 1
name = "node1"
message = coreapi.CoreNodeMessage.create(
MessageFlags.ADD.value,
[
(NodeTlvs.NUMBER, node_id),
(NodeTlvs.TYPE, node_type.value),
(NodeTlvs.NAME, name),
(NodeTlvs.X_POSITION, 0),
(NodeTlvs.Y_POSITION, 0),
(NodeTlvs.MODEL, model),
],
)
coretlv.handle_message(message)
node = coretlv.session.get_node(node_id, NodeBase)
assert node
assert node.name == name
def test_node_update(self, coretlv: CoreHandler):
node_id = 1
coretlv.session.add_node(CoreNode, _id=node_id)
x = 50
y = 100
message = coreapi.CoreNodeMessage.create(
0,
[
(NodeTlvs.NUMBER, node_id),
(NodeTlvs.X_POSITION, x),
(NodeTlvs.Y_POSITION, y),
],
)
coretlv.handle_message(message)
node = coretlv.session.get_node(node_id, NodeBase)
assert node is not None
assert node.position.x == x
assert node.position.y == y
def test_node_delete(self, coretlv: CoreHandler):
node_id = 1
coretlv.session.add_node(CoreNode, _id=node_id)
message = coreapi.CoreNodeMessage.create(
MessageFlags.DELETE.value, [(NodeTlvs.NUMBER, node_id)]
)
coretlv.handle_message(message)
with pytest.raises(CoreError):
coretlv.session.get_node(node_id, NodeBase)
def test_link_add_node_to_net(self, coretlv: CoreHandler):
node1_id = 1
coretlv.session.add_node(CoreNode, _id=node1_id)
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
iface1_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
switch_node = coretlv.session.get_node(switch_id, SwitchNode)
all_links = switch_node.links()
assert len(all_links) == 1
def test_link_add_net_to_node(self, coretlv: CoreHandler):
node1_id = 1
coretlv.session.add_node(CoreNode, _id=node1_id)
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
iface2_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, switch_id),
(LinkTlvs.N2_NUMBER, node1_id),
(LinkTlvs.IFACE2_NUMBER, 0),
(LinkTlvs.IFACE2_IP4, iface2_ip4),
(LinkTlvs.IFACE2_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
switch_node = coretlv.session.get_node(switch_id, SwitchNode)
all_links = switch_node.links()
assert len(all_links) == 1
def test_link_add_node_to_node(self, coretlv: CoreHandler):
node1_id = 1
coretlv.session.add_node(CoreNode, _id=node1_id)
node2_id = 2
coretlv.session.add_node(CoreNode, _id=node2_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
iface1_ip4 = str(ip_prefix[node1_id])
iface2_ip4 = str(ip_prefix[node2_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, node2_id),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
(LinkTlvs.IFACE2_NUMBER, 0),
(LinkTlvs.IFACE2_IP4, iface2_ip4),
(LinkTlvs.IFACE2_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
all_links = []
for node_id in coretlv.session.nodes:
node = coretlv.session.nodes[node_id]
all_links += node.links()
assert len(all_links) == 1
def test_link_update(self, coretlv: CoreHandler):
node1_id = 1
coretlv.session.add_node(CoreNode, _id=node1_id)
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
iface1_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
switch_node = coretlv.session.get_node(switch_id, SwitchNode)
all_links = switch_node.links()
assert len(all_links) == 1
link = all_links[0]
assert link.options.bandwidth is None
bandwidth = 50000
message = coreapi.CoreLinkMessage.create(
0,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.BANDWIDTH, bandwidth),
],
)
coretlv.handle_message(message)
switch_node = coretlv.session.get_node(switch_id, SwitchNode)
all_links = switch_node.links()
assert len(all_links) == 1
link = all_links[0]
assert link.options.bandwidth == bandwidth
def test_link_delete_node_to_node(self, coretlv: CoreHandler):
node1_id = 1
coretlv.session.add_node(CoreNode, _id=node1_id)
node2_id = 2
coretlv.session.add_node(CoreNode, _id=node2_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
iface1_ip4 = str(ip_prefix[node1_id])
iface2_ip4 = str(ip_prefix[node2_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, node2_id),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
(LinkTlvs.IFACE2_IP4, iface2_ip4),
(LinkTlvs.IFACE2_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
all_links = []
for node_id in coretlv.session.nodes:
node = coretlv.session.nodes[node_id]
all_links += node.links()
assert len(all_links) == 1
message = coreapi.CoreLinkMessage.create(
MessageFlags.DELETE.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, node2_id),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE2_NUMBER, 0),
],
)
coretlv.handle_message(message)
all_links = []
for node_id in coretlv.session.nodes:
node = coretlv.session.nodes[node_id]
all_links += node.links()
assert len(all_links) == 0
def test_link_delete_node_to_net(self, coretlv: CoreHandler):
node1_id = 1
coretlv.session.add_node(CoreNode, _id=node1_id)
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
iface1_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
switch_node = coretlv.session.get_node(switch_id, SwitchNode)
all_links = switch_node.links()
assert len(all_links) == 1
message = coreapi.CoreLinkMessage.create(
MessageFlags.DELETE.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.IFACE1_NUMBER, 0),
],
)
coretlv.handle_message(message)
switch_node = coretlv.session.get_node(switch_id, SwitchNode)
all_links = switch_node.links()
assert len(all_links) == 0
def test_link_delete_net_to_node(self, coretlv: CoreHandler):
node1_id = 1
coretlv.session.add_node(CoreNode, _id=node1_id)
switch_id = 2
coretlv.session.add_node(SwitchNode, _id=switch_id)
ip_prefix = netaddr.IPNetwork("10.0.0.0/24")
iface1_ip4 = str(ip_prefix[node1_id])
message = coreapi.CoreLinkMessage.create(
MessageFlags.ADD.value,
[
(LinkTlvs.N1_NUMBER, node1_id),
(LinkTlvs.N2_NUMBER, switch_id),
(LinkTlvs.IFACE1_NUMBER, 0),
(LinkTlvs.IFACE1_IP4, iface1_ip4),
(LinkTlvs.IFACE1_IP4_MASK, 24),
],
)
coretlv.handle_message(message)
switch_node = coretlv.session.get_node(switch_id, SwitchNode)
all_links = switch_node.links()
assert len(all_links) == 1
message = coreapi.CoreLinkMessage.create(
MessageFlags.DELETE.value,
[
(LinkTlvs.N1_NUMBER, switch_id),
(LinkTlvs.N2_NUMBER, node1_id),
(LinkTlvs.IFACE2_NUMBER, 0),
],
)
coretlv.handle_message(message)
switch_node = coretlv.session.get_node(switch_id, SwitchNode)
all_links = switch_node.links()
assert len(all_links) == 0
def test_session_update(self, coretlv: CoreHandler):
session_id = coretlv.session.id
name = "test"
message = coreapi.CoreSessionMessage.create(
0, [(SessionTlvs.NUMBER, str(session_id)), (SessionTlvs.NAME, name)]
)
coretlv.handle_message(message)
assert coretlv.session.name == name
def test_session_query(self, coretlv: CoreHandler):
coretlv.dispatch_replies = mock.MagicMock()
message = coreapi.CoreSessionMessage.create(MessageFlags.STRING.value, [])
coretlv.handle_message(message)
args, _ = coretlv.dispatch_replies.call_args
replies = args[0]
assert len(replies) == 1
def test_session_join(self, coretlv: CoreHandler):
coretlv.dispatch_replies = mock.MagicMock()
session_id = coretlv.session.id
message = coreapi.CoreSessionMessage.create(
MessageFlags.ADD.value, [(SessionTlvs.NUMBER, str(session_id))]
)
coretlv.handle_message(message)
assert coretlv.session.id == session_id
def test_session_delete(self, coretlv: CoreHandler):
assert len(coretlv.coreemu.sessions) == 1
session_id = coretlv.session.id
message = coreapi.CoreSessionMessage.create(
MessageFlags.DELETE.value, [(SessionTlvs.NUMBER, str(session_id))]
)
coretlv.handle_message(message)
assert len(coretlv.coreemu.sessions) == 0
def test_file_hook_add(self, coretlv: CoreHandler):
state = EventTypes.DATACOLLECT_STATE
assert coretlv.session.hooks.get(state) is None
file_name = "test.sh"
file_data = "echo hello"
message = coreapi.CoreFileMessage.create(
MessageFlags.ADD.value,
[
(FileTlvs.TYPE, f"hook:{state.value}"),
(FileTlvs.NAME, file_name),
(FileTlvs.DATA, file_data),
],
)
coretlv.handle_message(message)
hooks = coretlv.session.hooks.get(state)
assert len(hooks) == 1
name, data = hooks[0]
assert file_name == name
assert file_data == data
def test_file_service_file_set(self, coretlv: CoreHandler):
node = coretlv.session.add_node(CoreNode)
service = "DefaultRoute"
file_name = "defaultroute.sh"
file_data = "echo hello"
message = coreapi.CoreFileMessage.create(
MessageFlags.ADD.value,
[
(FileTlvs.NODE, node.id),
(FileTlvs.TYPE, f"service:{service}"),
(FileTlvs.NAME, file_name),
(FileTlvs.DATA, file_data),
],
)
coretlv.handle_message(message)
service_file = coretlv.session.services.get_service_file(
node, service, file_name
)
assert file_data == service_file.data
def test_file_node_file_copy(self, request, coretlv: CoreHandler):
file_path = Path("/var/log/test/node.log")
node = coretlv.session.add_node(CoreNode)
node.makenodedir()
file_data = "echo hello"
message = coreapi.CoreFileMessage.create(
MessageFlags.ADD.value,
[
(FileTlvs.NODE, node.id),
(FileTlvs.NAME, str(file_path)),
(FileTlvs.DATA, file_data),
],
)
coretlv.handle_message(message)
if not request.config.getoption("mock"):
expected_path = node.directory / "var.log/test" / file_path.name
assert expected_path.exists()
def test_exec_node_tty(self, coretlv: CoreHandler):
coretlv.dispatch_replies = mock.MagicMock()
node = coretlv.session.add_node(CoreNode)
message = coreapi.CoreExecMessage.create(
MessageFlags.TTY.value,
[
(ExecuteTlvs.NODE, node.id),
(ExecuteTlvs.NUMBER, 1),
(ExecuteTlvs.COMMAND, "bash"),
],
)
coretlv.handle_message(message)
args, _ = coretlv.dispatch_replies.call_args
replies = args[0]
assert len(replies) == 1
def test_exec_local_command(self, request, coretlv: CoreHandler):
if request.config.getoption("mock"):
pytest.skip("mocking calls")
coretlv.dispatch_replies = mock.MagicMock()
node = coretlv.session.add_node(CoreNode)
cmd = "echo hello"
message = coreapi.CoreExecMessage.create(
MessageFlags.TEXT.value | MessageFlags.LOCAL.value,
[
(ExecuteTlvs.NODE, node.id),
(ExecuteTlvs.NUMBER, 1),
(ExecuteTlvs.COMMAND, cmd),
],
)
coretlv.handle_message(message)
args, _ = coretlv.dispatch_replies.call_args
replies = args[0]
assert len(replies) == 1
def test_exec_node_command(self, coretlv: CoreHandler):
coretlv.dispatch_replies = mock.MagicMock()
node = coretlv.session.add_node(CoreNode)
cmd = "echo hello"
message = coreapi.CoreExecMessage.create(
MessageFlags.TEXT.value,
[
(ExecuteTlvs.NODE, node.id),
(ExecuteTlvs.NUMBER, 1),
(ExecuteTlvs.COMMAND, cmd),
],
)
node.cmd = MagicMock(return_value="hello")
coretlv.handle_message(message)
node.cmd.assert_called_with(cmd)
@pytest.mark.parametrize(
"state",
[
EventTypes.SHUTDOWN_STATE,
EventTypes.RUNTIME_STATE,
EventTypes.DATACOLLECT_STATE,
EventTypes.CONFIGURATION_STATE,
EventTypes.DEFINITION_STATE,
],
)
def test_event_state(self, coretlv: CoreHandler, state: EventTypes):
message = coreapi.CoreEventMessage.create(0, [(EventTlvs.TYPE, state.value)])
coretlv.handle_message(message)
assert coretlv.session.state == state
def test_event_schedule(self, coretlv: CoreHandler):
coretlv.session.add_event = mock.MagicMock()
node = coretlv.session.add_node(CoreNode)
message = coreapi.CoreEventMessage.create(
MessageFlags.ADD.value,
[
(EventTlvs.TYPE, EventTypes.SCHEDULED.value),
(EventTlvs.TIME, str(time.monotonic() + 100)),
(EventTlvs.NODE, node.id),
(EventTlvs.NAME, "event"),
(EventTlvs.DATA, "data"),
],
)
coretlv.handle_message(message)
coretlv.session.add_event.assert_called_once()
def test_event_save_xml(self, coretlv: CoreHandler, tmpdir):
xml_file = tmpdir.join("coretlv.session.xml")
file_path = xml_file.strpath
coretlv.session.add_node(CoreNode)
message = coreapi.CoreEventMessage.create(
0,
[(EventTlvs.TYPE, EventTypes.FILE_SAVE.value), (EventTlvs.NAME, file_path)],
)
coretlv.handle_message(message)
assert Path(file_path).exists()
def test_event_open_xml(self, coretlv: CoreHandler, tmpdir):
xml_file = tmpdir.join("coretlv.session.xml")
file_path = Path(xml_file.strpath)
node = coretlv.session.add_node(CoreNode)
coretlv.session.save_xml(file_path)
coretlv.session.delete_node(node.id)
message = coreapi.CoreEventMessage.create(
0,
[
(EventTlvs.TYPE, EventTypes.FILE_OPEN.value),
(EventTlvs.NAME, str(file_path)),
],
)
coretlv.handle_message(message)
assert coretlv.session.get_node(node.id, NodeBase)
@pytest.mark.parametrize(
"state",
[
EventTypes.START,
EventTypes.STOP,
EventTypes.RESTART,
EventTypes.PAUSE,
EventTypes.RECONFIGURE,
],
)
def test_event_service(self, coretlv: CoreHandler, state: EventTypes):
coretlv.session.broadcast_event = mock.MagicMock()
node = coretlv.session.add_node(CoreNode)
message = coreapi.CoreEventMessage.create(
0,
[
(EventTlvs.TYPE, state.value),
(EventTlvs.NODE, node.id),
(EventTlvs.NAME, "service:DefaultRoute"),
],
)
coretlv.handle_message(message)
coretlv.session.broadcast_event.assert_called_once()
@pytest.mark.parametrize(
"state",
[
EventTypes.START,
EventTypes.STOP,
EventTypes.RESTART,
EventTypes.PAUSE,
EventTypes.RECONFIGURE,
],
)
def test_event_mobility(self, coretlv: CoreHandler, state: EventTypes):
message = coreapi.CoreEventMessage.create(
0, [(EventTlvs.TYPE, state.value), (EventTlvs.NAME, "mobility:ns2script")]
)
coretlv.handle_message(message)
def test_register_gui(self, coretlv: CoreHandler):
message = coreapi.CoreRegMessage.create(0, [(RegisterTlvs.GUI, "gui")])
coretlv.handle_message(message)
def test_register_xml(self, coretlv: CoreHandler, tmpdir):
xml_file = tmpdir.join("coretlv.session.xml")
file_path = xml_file.strpath
node = coretlv.session.add_node(CoreNode)
coretlv.session.save_xml(file_path)
coretlv.session.delete_node(node.id)
message = coreapi.CoreRegMessage.create(
0, [(RegisterTlvs.EXECUTE_SERVER, file_path)]
)
coretlv.session.instantiate()
coretlv.handle_message(message)
assert coretlv.coreemu.sessions[1].get_node(node.id, CoreNode)
def test_register_python(self, coretlv: CoreHandler, tmpdir):
xml_file = tmpdir.join("test.py")
file_path = xml_file.strpath
with open(file_path, "w") as f:
f.write("from core.nodes.base import CoreNode\n")
f.write("coreemu = globals()['coreemu']\n")
f.write(f"session = coreemu.sessions[{coretlv.session.id}]\n")
f.write("session.add_node(CoreNode)\n")
message = coreapi.CoreRegMessage.create(
0, [(RegisterTlvs.EXECUTE_SERVER, file_path)]
)
coretlv.session.instantiate()
coretlv.handle_message(message)
assert len(coretlv.session.nodes) == 1
def test_config_all(self, coretlv: CoreHandler):
message = coreapi.CoreConfMessage.create(
MessageFlags.ADD.value,
[(ConfigTlvs.OBJECT, "all"), (ConfigTlvs.TYPE, ConfigFlags.RESET.value)],
)
coretlv.session.location.refxyz = (10, 10, 10)
coretlv.handle_message(message)
assert coretlv.session.location.refxyz == (0, 0, 0)
def test_config_options_request(self, coretlv: CoreHandler):
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "session"),
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
],
)
coretlv.handle_broadcast_config = mock.MagicMock()
coretlv.handle_message(message)
coretlv.handle_broadcast_config.assert_called_once()
def test_config_options_update(self, coretlv: CoreHandler):
test_key = "test"
test_value = "test"
values = {test_key: test_value}
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "session"),
(ConfigTlvs.TYPE, ConfigFlags.UPDATE.value),
(ConfigTlvs.VALUES, dict_to_str(values)),
],
)
coretlv.handle_message(message)
assert coretlv.session.options.get_config(test_key) == test_value
def test_config_location_reset(self, coretlv: CoreHandler):
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "location"),
(ConfigTlvs.TYPE, ConfigFlags.RESET.value),
],
)
coretlv.session.location.refxyz = (10, 10, 10)
coretlv.handle_message(message)
assert coretlv.session.location.refxyz == (0, 0, 0)
def test_config_location_update(self, coretlv: CoreHandler):
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "location"),
(ConfigTlvs.TYPE, ConfigFlags.UPDATE.value),
(ConfigTlvs.VALUES, "10|10|70|50|0|0.5"),
],
)
coretlv.handle_message(message)
assert coretlv.session.location.refxyz == (10, 10, 0.0)
assert coretlv.session.location.refgeo == (70, 50, 0)
assert coretlv.session.location.refscale == 0.5
def test_config_metadata_request(self, coretlv: CoreHandler):
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "metadata"),
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
],
)
coretlv.handle_broadcast_config = mock.MagicMock()
coretlv.handle_message(message)
coretlv.handle_broadcast_config.assert_called_once()
def test_config_metadata_update(self, coretlv: CoreHandler):
test_key = "test"
test_value = "test"
values = {test_key: test_value}
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "metadata"),
(ConfigTlvs.TYPE, ConfigFlags.UPDATE.value),
(ConfigTlvs.VALUES, dict_to_str(values)),
],
)
coretlv.handle_message(message)
assert coretlv.session.metadata[test_key] == test_value
def test_config_broker_request(self, coretlv: CoreHandler):
server = "test"
host = "10.0.0.1"
port = 50000
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "broker"),
(ConfigTlvs.TYPE, ConfigFlags.UPDATE.value),
(ConfigTlvs.VALUES, f"{server}:{host}:{port}"),
],
)
coretlv.session.distributed.add_server = mock.MagicMock()
coretlv.handle_message(message)
coretlv.session.distributed.add_server.assert_called_once_with(server, host)
def test_config_services_request_all(self, coretlv: CoreHandler):
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "services"),
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
],
)
coretlv.handle_broadcast_config = mock.MagicMock()
coretlv.handle_message(message)
coretlv.handle_broadcast_config.assert_called_once()
def test_config_services_request_specific(self, coretlv: CoreHandler):
node = coretlv.session.add_node(CoreNode)
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.NODE, node.id),
(ConfigTlvs.OBJECT, "services"),
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
(ConfigTlvs.OPAQUE, "service:DefaultRoute"),
],
)
coretlv.handle_broadcast_config = mock.MagicMock()
coretlv.handle_message(message)
coretlv.handle_broadcast_config.assert_called_once()
def test_config_services_request_specific_file(self, coretlv: CoreHandler):
node = coretlv.session.add_node(CoreNode)
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.NODE, node.id),
(ConfigTlvs.OBJECT, "services"),
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
(ConfigTlvs.OPAQUE, "service:DefaultRoute:defaultroute.sh"),
],
)
coretlv.session.broadcast_file = mock.MagicMock()
coretlv.handle_message(message)
coretlv.session.broadcast_file.assert_called_once()
def test_config_services_reset(self, coretlv: CoreHandler):
node = coretlv.session.add_node(CoreNode)
service = "DefaultRoute"
coretlv.session.services.set_service(node.id, service)
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "services"),
(ConfigTlvs.TYPE, ConfigFlags.RESET.value),
],
)
assert coretlv.session.services.get_service(node.id, service) is not None
coretlv.handle_message(message)
assert coretlv.session.services.get_service(node.id, service) is None
def test_config_services_set(self, coretlv: CoreHandler):
node = coretlv.session.add_node(CoreNode)
service = "DefaultRoute"
values = {"meta": "metadata"}
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.NODE, node.id),
(ConfigTlvs.OBJECT, "services"),
(ConfigTlvs.TYPE, ConfigFlags.UPDATE.value),
(ConfigTlvs.OPAQUE, f"service:{service}"),
(ConfigTlvs.VALUES, dict_to_str(values)),
],
)
assert coretlv.session.services.get_service(node.id, service) is None
coretlv.handle_message(message)
assert coretlv.session.services.get_service(node.id, service) is not None
def test_config_mobility_reset(self, coretlv: CoreHandler):
wlan = coretlv.session.add_node(WlanNode)
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.OBJECT, "MobilityManager"),
(ConfigTlvs.TYPE, ConfigFlags.RESET.value),
],
)
coretlv.session.mobility.set_model_config(wlan.id, BasicRangeModel.name, {})
assert len(coretlv.session.mobility.node_configurations) == 1
coretlv.handle_message(message)
assert len(coretlv.session.mobility.node_configurations) == 0
def test_config_mobility_model_request(self, coretlv: CoreHandler):
wlan = coretlv.session.add_node(WlanNode)
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.NODE, wlan.id),
(ConfigTlvs.OBJECT, BasicRangeModel.name),
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
],
)
coretlv.handle_broadcast_config = mock.MagicMock()
coretlv.handle_message(message)
coretlv.handle_broadcast_config.assert_called_once()
def test_config_mobility_model_update(self, coretlv: CoreHandler):
wlan = coretlv.session.add_node(WlanNode)
config_key = "range"
config_value = "1000"
values = {config_key: config_value}
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.NODE, wlan.id),
(ConfigTlvs.OBJECT, BasicRangeModel.name),
(ConfigTlvs.TYPE, ConfigFlags.UPDATE.value),
(ConfigTlvs.VALUES, dict_to_str(values)),
],
)
coretlv.handle_message(message)
config = coretlv.session.mobility.get_model_config(
wlan.id, BasicRangeModel.name
)
assert config[config_key] == config_value
def test_config_emane_model_request(self, coretlv: CoreHandler):
wlan = coretlv.session.add_node(WlanNode)
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.NODE, wlan.id),
(ConfigTlvs.OBJECT, EmaneIeee80211abgModel.name),
(ConfigTlvs.TYPE, ConfigFlags.REQUEST.value),
],
)
coretlv.handle_broadcast_config = mock.MagicMock()
coretlv.handle_message(message)
coretlv.handle_broadcast_config.assert_called_once()
def test_config_emane_model_update(self, coretlv: CoreHandler):
wlan = coretlv.session.add_node(WlanNode)
config_key = "distance"
config_value = "50051"
values = {config_key: config_value}
message = coreapi.CoreConfMessage.create(
0,
[
(ConfigTlvs.NODE, wlan.id),
(ConfigTlvs.OBJECT, EmaneIeee80211abgModel.name),
(ConfigTlvs.TYPE, ConfigFlags.UPDATE.value),
(ConfigTlvs.VALUES, dict_to_str(values)),
],
)
coretlv.handle_message(message)
config = coretlv.session.emane.get_config(wlan.id, EmaneIeee80211abgModel.name)
assert config[config_key] == config_value

View file

@ -432,7 +432,7 @@ firewall is not blocking the GRE traffic.
The host machine that runs the CORE GUI and/or daemon is not necessarily
accessible from a node. Running an X11 application on a node, for example,
requires some channel of communication for the application to connect with
the X server for graphical display. There are several different ways to
the X server for graphical display. There are different ways to
connect from the node to the host and vice versa.
#### Control Network
@ -449,12 +449,6 @@ the node, and SSH with X11 forwarding can be used from the host to the node.
ssh -X 172.16.0.5 xclock
```
Note that the **coresendmsg** utility can be used for a node to send
messages to the CORE daemon running on the host (if the **listenaddr = 0.0.0.0**
is set in the **/etc/core/core.conf** file) to interact with the running
emulation. For example, a node may move itself or other nodes, or change
its icon based on some node state.
#### Other Methods
There are still other ways to connect a host with a node. The RJ45 Tool
@ -553,9 +547,9 @@ See the [EMANE](emane.md) chapter for details on using EMANE.
CORE has a few ways to script mobility.
| Option | Description |
|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ns-2 script | The script specifies either absolute positions or waypoints with a velocity. Locations are given with Cartesian coordinates. |
| CORE API | An external entity can move nodes by sending CORE API Node messages with updated X,Y coordinates; the **coresendmsg** utility allows a shell script to generate these messages. |
| gRPC API | An external entity can move nodes by leveraging the gRPC API |
| EMANE events | See [EMANE](emane.md) for details on using EMANE scripts to move nodes around. Location information is typically given as latitude, longitude, and altitude. |
For the first method, you can create a mobility script using a text

View file

@ -74,7 +74,6 @@ After the installation complete it will have installed the following scripts.
| core-cli | tool to query, open xml files, and send commands using gRPC |
| core-daemon | runs the backed core server providing a gRPC API |
| core-gui | starts GUI |
| core-manage | tool to add, remove, or check for services, models, and node types |
| core-python | provides a convenience for running the core python virtual environment |
| core-route-monitor | tool to help monitor traffic across nodes and feed that to SDT |
| core-service-update | tool to update automate modifying a legacy service to match current naming |

View file

@ -1,21 +1,10 @@
# CORE
# (c)2012-2013 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
# Makefile for building man pages.
#
if WANT_GUI
GUI_MANS = core-gui.1
endif
if WANT_DAEMON
DAEMON_MANS = vnoded.1 vcmd.1 netns.1 core-daemon.1 coresendmsg.1 \
core-cleanup.1 core-manage.1
DAEMON_MANS = vnoded.1 vcmd.1 netns.1 core-daemon.1 core-gui.1 \
core-cleanup.1
endif
man_MANS = $(GUI_MANS) $(DAEMON_MANS)
man_MANS = $(DAEMON_MANS)
.PHONY: generate-mans
generate-mans:
@ -24,9 +13,7 @@ generate-mans:
$(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/vcmd -o vcmd.1
$(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/netns -o netns.1
$(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/scripts/core-daemon -o core-daemon.1
$(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/scripts/coresendmsg -o coresendmsg.1
$(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/scripts/core-cleanup -o core-cleanup.1
$(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/scripts/core-manage -o core-manage.1
.PHONY: diff
diff:

View file

@ -1,31 +0,0 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
.TH CORE-MANAGE "1" "June 2020" "CORE" "User Commands"
.SH NAME
core-manage \- manual page for core-manage 6.4.0
.SH SYNOPSIS
.B core-manage
[\fI\,-h\/\fR] [\fI\,options\/\fR] \fI\,<action> <target> <string>\/\fR
.SH DESCRIPTION
Helper tool to add, remove, or check for services, models, and node types
in a CORE installation.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-\-userpath\fR=\fI\,USERPATH\/\fR
use the specified user path (e.g. "$HOME/.core") to
access nodes.conf
.TP
\fB\-v\fR, \fB\-\-verbose\fR
be verbose when performing action
.SH EXAMPLES
.IP
core\-manage add service newrouting
core\-manage \-v check model RfPipe
core\-manage \-\-userpath="$HOME/.core" add nodetype "{ftp ftp.gif ftp.gif {DefaultRoute FTP} netns {FTP server} }"
.SS "Arguments:"
.IP
<action> should be one of: add, remove, check
<target> should be one of: service, model, nodetype
<string> is the text to add, remove, check

View file

@ -1,40 +0,0 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
.TH CORESENDMSG "1" "June 2020" "CORE" "User Commands"
.SH NAME
coresendmsg \- manual page for coresendmsg 6.4.0
.SH SYNOPSIS
.B coresendmsg
[\fI\,-h|-H\/\fR] [\fI\,options\/\fR] [\fI\,message-type\/\fR] [\fI\,flags=flags\/\fR] [\fI\,message-TLVs\/\fR]
.SH DESCRIPTION
.SS "Supported message types:"
.IP
node link execute register config file interface event session exception
.SS "Supported message flags (flags=f1,f2,...):"
.IP
none add delete cri local string text tty
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-H\fR
show example usage help message and exit
.TP
\fB\-p\fR PORT, \fB\-\-port\fR=\fI\,PORT\/\fR
TCP port to connect to, default: 4038
.TP
\fB\-a\fR ADDRESS, \fB\-\-address\fR=\fI\,ADDRESS\/\fR
Address to connect to, default: localhost
.TP
\fB\-s\fR SESSION, \fB\-\-session\fR=\fI\,SESSION\/\fR
Session to join, default: None
.TP
\fB\-l\fR, \fB\-\-listen\fR
Listen for a response message and print it.
.TP
\fB\-t\fR, \fB\-\-list\-tlvs\fR
List TLVs for the specified message type.
.TP
\fB\-\-tcp\fR
Use TCP instead of UDP and connect to a session
default: False

View file

@ -1,8 +1,4 @@
# CORE
# (c)2010-2013 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
#
# Makefile for building netns.
#

View file

@ -1,9 +1,5 @@
/*
* CORE
* Copyright (c)2012 the Boeing Company.
* See the LICENSE file included in this distribution.
*
* author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
*
* version.h
*