core-extra/daemon/scripts/core-daemon
2019-09-10 14:20:51 -07:00

169 lines
5.5 KiB
Python
Executable file

#!/usr/bin/env python
"""
core-daemon: the CORE daemon is a server process that receives CORE API
messages and instantiates emulated nodes and networks within the kernel. Various
message handlers are defined and some support for sending messages.
"""
import argparse
import logging
import sys
import threading
import time
from configparser import ConfigParser
from core import constants, load_logging_config
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.emulator import enumerations
from core.utils import close_onexec
def banner():
"""
Output the program banner printed to the terminal or log file.
:return: nothing
"""
logging.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)
mainserver.udpthread.daemon = True
mainserver.udpthread.start()
def cored(cfg, use_ovs):
"""
Start the CoreServer object and enter the server loop.
:param dict cfg: core configuration
:param bool use_ovs: flag to determine if ovs nodes should be used
: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)
if use_ovs:
from core.nodes.openvswitch import OVS_NODES
server.coreemu.update_nodes(OVS_NODES)
except:
logging.exception("error starting main server on: %s:%s", host, port)
sys.exit(1)
# initialize grpc api
if cfg["grpc"] == "True":
grpc_server = CoreGrpcServer(server.coreemu)
grpc_address = "%s:%s" % (cfg["grpcaddress"], cfg["grpcport"])
grpc_thread = threading.Thread(target=grpc_server.listen, args=(grpc_address,))
grpc_thread.daemon = True
grpc_thread.start()
# start udp server
start_udp(server, address)
# close handlers
close_onexec(server.fileno())
logging.info("tcp/udp servers started, listening on: %s:%s", host, port)
server.serve_forever()
def get_merged_config(filename):
"""
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
"""
# these are the defaults used in the config file
defaults = {
"port": "%d" % enumerations.CORE_API_PORT,
"listenaddr": "localhost",
"xmlfilever": "1.0",
"numthreads": "1",
"grpcport": "50051",
"grpcaddress": "localhost",
"logfile": None
}
parser = argparse.ArgumentParser(
description="CORE daemon v.%s instantiates Linux network namespace nodes." % constants.COREDPY_VERSION)
parser.add_argument("-f", "--configfile", dest="configfile",
help="read config from specified file; default = %s" % filename)
parser.add_argument("-p", "--port", dest="port", type=int,
help="port number to listen on; default = %s" % defaults["port"])
parser.add_argument("-n", "--numthreads", dest="numthreads", type=int,
help="number of server threads; default = %s" % defaults["numthreads"])
parser.add_argument("--ovs", action="store_true", help="enable experimental ovs mode, default is false")
parser.add_argument("--grpc", action="store_true", help="enable grpc api, default is false")
parser.add_argument("--grpc-port", dest="grpcport",
help="grpc port to listen on; default %s" % defaults["grpcport"])
parser.add_argument("--grpc-address", dest="grpcaddress",
help="grpc address to listen on; default %s" % defaults["grpcaddress"])
parser.add_argument("-l", "--logfile", help="core logging configuration; default %s" % defaults["logfile"])
# parse command line options
args = parser.parse_args()
# read the config file
if args.configfile is not None:
filename = args.configfile
del args.configfile
cfg = ConfigParser(defaults)
cfg.read(filename)
# load logging configuration
load_logging_config(args.logfile)
section = "core-daemon"
if not cfg.has_section(section):
cfg.add_section(section)
# merge command line with config file
for opt in args.__dict__:
val = args.__dict__[opt]
if val is not None:
cfg.set(section, opt, str(val))
return dict(cfg.items(section))
def main():
"""
Main program startup.
:return: nothing
"""
# get a configuration merged from config file and command-line arguments
cfg = get_merged_config("%s/core.conf" % constants.CORE_CONF_DIR)
banner()
# check if ovs flag was provided
use_ovs = len(sys.argv) == 2 and sys.argv[1] == "ovs"
try:
cored(cfg, use_ovs)
except KeyboardInterrupt:
logging.info("keyboard interrupt, stopping core daemon")
if __name__ == "__main__":
main()