2013-08-29 15:21:13 +01:00
|
|
|
#!/usr/bin/env python
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
|
|
|
core-daemon: the CORE daemon is a server process that receives CORE API
|
2013-08-29 15:21:13 +01:00
|
|
|
messages and instantiates emulated nodes and networks within the kernel. Various
|
|
|
|
message handlers are defined and some support for sending messages.
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
2013-08-29 15:21:13 +01:00
|
|
|
|
2019-03-02 21:04:55 +00:00
|
|
|
import argparse
|
2019-02-16 17:50:19 +00:00
|
|
|
import logging
|
2019-10-04 20:36:15 +01:00
|
|
|
import os
|
2017-04-25 16:45:34 +01:00
|
|
|
import sys
|
2019-02-19 06:54:14 +00:00
|
|
|
import threading
|
2017-04-25 16:45:34 +01:00
|
|
|
import time
|
2019-06-07 18:05:40 +01:00
|
|
|
from configparser import ConfigParser
|
|
|
|
|
2019-09-28 07:29:15 +01:00
|
|
|
from core import constants
|
2019-06-07 18:05:40 +01:00
|
|
|
from core.api.grpc.server import CoreGrpcServer
|
2019-09-10 22:20:51 +01:00
|
|
|
from core.api.tlv.corehandlers import CoreHandler, CoreUdpHandler
|
|
|
|
from core.api.tlv.coreserver import CoreServer, CoreUdpServer
|
2020-03-22 21:09:38 +00:00
|
|
|
from core.api.tlv.enumerations import CORE_API_PORT
|
2019-10-18 18:33:31 +01:00
|
|
|
from core.constants import CORE_CONF_DIR, COREDPY_VERSION
|
2019-09-28 07:29:15 +01:00
|
|
|
from core.utils import close_onexec, load_logging_config
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
def banner():
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
2017-05-04 21:49:14 +01:00
|
|
|
Output the program banner printed to the terminal or log file.
|
|
|
|
|
|
|
|
:return: nothing
|
|
|
|
"""
|
2019-02-16 17:50:19 +00:00
|
|
|
logging.info("CORE daemon v.%s started %s", constants.COREDPY_VERSION, time.ctime())
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
|
2019-06-06 19:33:22 +01:00
|
|
|
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)
|
2020-04-03 01:33:38 +01:00
|
|
|
mainserver.udpthread = threading.Thread(target=mainserver.udpserver.start, daemon=True)
|
2019-06-06 19:33:22 +01:00
|
|
|
mainserver.udpthread.start()
|
|
|
|
|
|
|
|
|
2019-09-26 23:20:32 +01:00
|
|
|
def cored(cfg):
|
2017-05-04 21:49:14 +01:00
|
|
|
"""
|
|
|
|
Start the CoreServer object and enter the server loop.
|
|
|
|
|
|
|
|
:param dict cfg: core configuration
|
|
|
|
:return: nothing
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
|
|
|
host = cfg["listenaddr"]
|
|
|
|
port = int(cfg["port"])
|
|
|
|
if host == "" or host is None:
|
2013-08-29 15:21:13 +01:00
|
|
|
host = "localhost"
|
2018-03-23 16:57:37 +00:00
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
try:
|
2019-06-06 19:33:22 +01:00
|
|
|
address = (host, port)
|
|
|
|
server = CoreServer(address, CoreHandler, cfg)
|
2017-05-04 21:49:14 +01:00
|
|
|
except:
|
2019-02-16 17:50:19 +00:00
|
|
|
logging.exception("error starting main server on: %s:%s", host, port)
|
2013-08-29 15:21:13 +01:00
|
|
|
sys.exit(1)
|
2017-05-04 21:49:14 +01:00
|
|
|
|
2019-02-19 06:54:14 +00:00
|
|
|
# initialize grpc api
|
2019-10-18 22:28:50 +01:00
|
|
|
grpc_server = CoreGrpcServer(server.coreemu)
|
|
|
|
address_config = cfg["grpcaddress"]
|
|
|
|
port_config = cfg["grpcport"]
|
|
|
|
grpc_address = f"{address_config}:{port_config}"
|
2020-04-03 01:33:38 +01:00
|
|
|
grpc_thread = threading.Thread(target=grpc_server.listen, args=(grpc_address,), daemon=True)
|
2019-10-18 22:28:50 +01:00
|
|
|
grpc_thread.start()
|
2019-02-19 06:54:14 +00:00
|
|
|
|
2019-06-06 19:43:39 +01:00
|
|
|
# start udp server
|
|
|
|
start_udp(server, address)
|
|
|
|
|
|
|
|
# close handlers
|
2018-03-02 17:15:52 +00:00
|
|
|
close_onexec(server.fileno())
|
2019-06-06 19:43:39 +01:00
|
|
|
|
2019-09-11 23:05:05 +01:00
|
|
|
logging.info("CORE TLV API TCP/UDP listening on: %s:%s", host, port)
|
2013-08-29 15:21:13 +01:00
|
|
|
server.serve_forever()
|
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
|
|
|
|
def get_merged_config(filename):
|
2017-05-04 21:49:14 +01:00
|
|
|
"""
|
|
|
|
Return a configuration after merging config file and command-line arguments.
|
|
|
|
|
|
|
|
:param str filename: file name to merge configuration settings with
|
|
|
|
:return: merged configuration
|
|
|
|
:rtype: dict
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
2013-08-29 15:21:13 +01:00
|
|
|
# these are the defaults used in the config file
|
2019-10-18 18:33:31 +01:00
|
|
|
default_log = os.path.join(constants.CORE_CONF_DIR, "logging.conf")
|
|
|
|
default_grpc_port = "50051"
|
|
|
|
default_threads = "1"
|
|
|
|
default_address = "localhost"
|
2018-03-23 16:57:37 +00:00
|
|
|
defaults = {
|
2019-10-18 18:33:31 +01:00
|
|
|
"port": str(CORE_API_PORT),
|
|
|
|
"listenaddr": default_address,
|
|
|
|
"numthreads": default_threads,
|
|
|
|
"grpcport": default_grpc_port,
|
|
|
|
"grpcaddress": default_address,
|
|
|
|
"logfile": default_log
|
2018-03-23 16:57:37 +00:00
|
|
|
}
|
2013-08-29 15:21:13 +01:00
|
|
|
|
2019-03-02 21:04:55 +00:00
|
|
|
parser = argparse.ArgumentParser(
|
2019-10-18 18:33:31 +01:00
|
|
|
description=f"CORE daemon v.{COREDPY_VERSION} instantiates Linux network namespace nodes.")
|
2019-03-02 21:04:55 +00:00
|
|
|
parser.add_argument("-f", "--configfile", dest="configfile",
|
2019-10-18 18:33:31 +01:00
|
|
|
help=f"read config from specified file; default = {filename}")
|
2019-03-02 21:04:55 +00:00
|
|
|
parser.add_argument("-p", "--port", dest="port", type=int,
|
2019-10-18 18:33:31 +01:00
|
|
|
help=f"port number to listen on; default = {CORE_API_PORT}")
|
2019-03-02 21:04:55 +00:00
|
|
|
parser.add_argument("-n", "--numthreads", dest="numthreads", type=int,
|
2019-10-18 18:33:31 +01:00
|
|
|
help=f"number of server threads; default = {default_threads}")
|
2019-03-02 21:04:55 +00:00
|
|
|
parser.add_argument("--ovs", action="store_true", help="enable experimental ovs mode, default is false")
|
2019-05-31 00:31:48 +01:00
|
|
|
parser.add_argument("--grpc-port", dest="grpcport",
|
2019-10-18 18:33:31 +01:00
|
|
|
help=f"grpc port to listen on; default {default_grpc_port}")
|
2019-05-31 00:31:48 +01:00
|
|
|
parser.add_argument("--grpc-address", dest="grpcaddress",
|
2019-10-18 18:33:31 +01:00
|
|
|
help=f"grpc address to listen on; default {default_address}")
|
|
|
|
parser.add_argument("-l", "--logfile", help=f"core logging configuration; default {default_log}")
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
# parse command line options
|
2019-03-02 21:04:55 +00:00
|
|
|
args = parser.parse_args()
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
# read the config file
|
2019-03-02 21:04:55 +00:00
|
|
|
if args.configfile is not None:
|
|
|
|
filename = args.configfile
|
|
|
|
del args.configfile
|
2019-06-04 02:22:25 +01:00
|
|
|
cfg = ConfigParser(defaults)
|
2013-08-29 15:21:13 +01:00
|
|
|
cfg.read(filename)
|
|
|
|
|
|
|
|
section = "core-daemon"
|
|
|
|
if not cfg.has_section(section):
|
|
|
|
cfg.add_section(section)
|
2017-04-25 16:45:34 +01:00
|
|
|
|
2019-09-30 19:51:40 +01:00
|
|
|
# merge argparse with configparser
|
|
|
|
for opt in vars(args):
|
|
|
|
val = getattr(args, opt)
|
2013-08-29 15:21:13 +01:00
|
|
|
if val is not None:
|
2019-03-02 21:04:55 +00:00
|
|
|
cfg.set(section, opt, str(val))
|
2013-08-29 15:21:13 +01:00
|
|
|
|
2019-03-02 21:04:55 +00:00
|
|
|
return dict(cfg.items(section))
|
2013-08-29 15:21:13 +01:00
|
|
|
|
2017-04-25 16:45:34 +01:00
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
def main():
|
2017-05-04 21:49:14 +01:00
|
|
|
"""
|
|
|
|
Main program startup.
|
|
|
|
|
|
|
|
:return: nothing
|
2017-04-25 16:45:34 +01:00
|
|
|
"""
|
2013-08-29 15:21:13 +01:00
|
|
|
# get a configuration merged from config file and command-line arguments
|
2019-10-18 18:33:31 +01:00
|
|
|
cfg = get_merged_config(f"{CORE_CONF_DIR}/core.conf")
|
2019-10-04 20:36:15 +01:00
|
|
|
|
|
|
|
# load logging configuration
|
|
|
|
load_logging_config(cfg["logfile"])
|
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
banner()
|
2018-03-23 16:57:37 +00:00
|
|
|
|
2013-08-29 15:21:13 +01:00
|
|
|
try:
|
2019-09-26 23:20:32 +01:00
|
|
|
cored(cfg)
|
2013-08-29 15:21:13 +01:00
|
|
|
except KeyboardInterrupt:
|
2019-02-16 17:50:19 +00:00
|
|
|
logging.info("keyboard interrupt, stopping core daemon")
|
2013-08-29 15:21:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|