added config service manager to CoreEmu and made it possible to create a session and nodes with config services from a script

This commit is contained in:
Blake Harnden 2020-01-17 21:09:51 -08:00
parent 191a9e9909
commit dcc683dd38
8 changed files with 41 additions and 37 deletions

View file

@ -40,12 +40,6 @@ class ConfigService(abc.ABC):
configs = self.default_configs[:] configs = self.default_configs[:]
self._define_config(configs) self._define_config(configs)
def __hash__(self) -> int:
return hash(self.name)
def __eq__(self, other: "ConfigService") -> bool:
return self.name == other.name
@property @property
@abc.abstractmethod @abc.abstractmethod
def name(self) -> str: def name(self) -> str:

View file

@ -1,23 +1,21 @@
import logging import logging
import pathlib import pathlib
from typing import List from typing import List, Type
from core import utils from core import utils
from core.configservice.base import ConfigService from core.configservice.base import ConfigService
from core.errors import CoreError from core.errors import CoreError
from core.nodes.base import CoreNode
class ConfigServiceManager: class ConfigServiceManager:
def __init__(self): def __init__(self):
self.services = {} self.services = {}
def set_service(self, node: CoreNode, name: str) -> None: def get_service(self, name: str) -> Type[ConfigService]:
service_class = self.services.get(name) service_class = self.services.get(name)
if service_class in node.config_services: if service_class is None:
raise CoreError(f"node already has service {name}") raise CoreError(f"service does not exit {name}")
service = service_class(node) return service_class
node.config_services.add(service)
def add(self, service: ConfigService) -> None: def add(self, service: ConfigService) -> None:
name = service.name name = service.name

View file

@ -1,6 +1,5 @@
#!/bin/sh #!/bin/sh
# auto-generated by DefaultRoute service # auto-generated by DefaultRoute service
# config: ${config}
% for address in addresses: % for address in addresses:
ip route add default via ${address} ip route add default via ${address}
% endfor % endfor

View file

@ -6,6 +6,8 @@ import sys
from typing import Mapping, Type from typing import Mapping, Type
import core.services import core.services
from core import configservices
from core.configservice.manager import ConfigServiceManager
from core.emulator.session import Session from core.emulator.session import Session
from core.services.coreservices import ServiceManager from core.services.coreservices import ServiceManager
@ -55,6 +57,11 @@ class CoreEmu:
self.service_errors = [] self.service_errors = []
self.load_services() self.load_services()
# config services
self.service_manager = ConfigServiceManager()
config_services_path = os.path.abspath(os.path.dirname(configservices.__file__))
self.service_manager.load(config_services_path)
# catch exit event # catch exit event
atexit.register(self.shutdown) atexit.register(self.shutdown)
@ -97,6 +104,7 @@ class CoreEmu:
while _id in self.sessions: while _id in self.sessions:
_id += 1 _id += 1
session = _cls(_id, config=self.config) session = _cls(_id, config=self.config)
session.service_manager = self.service_manager
logging.info("created session: %s", _id) logging.info("created session: %s", _id)
self.sessions[_id] = session self.sessions[_id] = session
return session return session

View file

@ -75,6 +75,7 @@ class NodeOptions:
self.icon = None self.icon = None
self.opaque = None self.opaque = None
self.services = [] self.services = []
self.config_services = []
self.x = None self.x = None
self.y = None self.y = None
self.lat = None self.lat = None

View file

@ -161,6 +161,9 @@ class Session:
"host": ("DefaultRoute", "SSH"), "host": ("DefaultRoute", "SSH"),
} }
# config services
self.service_manager = None
@classmethod @classmethod
def get_node_class(cls, _type: NodeTypes) -> Type[NodeBase]: def get_node_class(cls, _type: NodeTypes) -> Type[NodeBase]:
""" """
@ -726,6 +729,11 @@ class Session:
logging.debug("set node type: %s", node.type) logging.debug("set node type: %s", node.type)
self.services.add_services(node, node.type, options.services) self.services.add_services(node, node.type, options.services)
# add config services
for name in options.config_services:
service_class = self.service_manager.get_service(name)
node.add_config_service(service_class)
# ensure default emane configuration # ensure default emane configuration
if isinstance(node, EmaneNet) and options.emane: if isinstance(node, EmaneNet) and options.emane:
self.emane.set_model_config(_id, options.emane) self.emane.set_model_config(_id, options.emane)
@ -1602,7 +1610,8 @@ class Session:
logging.info("booting node(%s): %s", node.name, [x.name for x in node.services]) logging.info("booting node(%s): %s", node.name, [x.name for x in node.services])
self.add_remove_control_interface(node=node, remove=False) self.add_remove_control_interface(node=node, remove=False)
self.services.boot_services(node) self.services.boot_services(node)
node.start_config_services() for service in node.config_services.values():
service.start()
def boot_nodes(self) -> List[Exception]: def boot_nodes(self) -> List[Exception]:
""" """

View file

@ -6,7 +6,7 @@ import logging
import os import os
import shutil import shutil
import threading import threading
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Type
import netaddr import netaddr
@ -14,7 +14,7 @@ from core import utils
from core.constants import MOUNT_BIN, VNODED_BIN from core.constants import MOUNT_BIN, VNODED_BIN
from core.emulator.data import LinkData, NodeData from core.emulator.data import LinkData, NodeData
from core.emulator.enumerations import LinkTypes, NodeTypes from core.emulator.enumerations import LinkTypes, NodeTypes
from core.errors import CoreCommandError from core.errors import CoreCommandError, CoreError
from core.nodes import client from core.nodes import client
from core.nodes.interface import CoreInterface, TunTap, Veth from core.nodes.interface import CoreInterface, TunTap, Veth
from core.nodes.netclient import LinuxNetClient, get_net_client from core.nodes.netclient import LinuxNetClient, get_net_client
@ -22,6 +22,9 @@ from core.nodes.netclient import LinuxNetClient, get_net_client
if TYPE_CHECKING: if TYPE_CHECKING:
from core.emulator.distributed import DistributedServer from core.emulator.distributed import DistributedServer
from core.emulator.session import Session from core.emulator.session import Session
from core.configservice.base import ConfigService
ConfigServiceType = Type[ConfigService]
_DEFAULT_MTU = 1500 _DEFAULT_MTU = 1500
@ -277,18 +280,21 @@ class CoreNodeBase(NodeBase):
""" """
super().__init__(session, _id, name, start, server) super().__init__(session, _id, name, start, server)
self.services = [] self.services = []
self.config_services = set() self.config_services = {}
self.nodedir = None self.nodedir = None
self.tmpnodedir = False self.tmpnodedir = False
def start_config_services(self) -> None: def add_config_service(self, service_class: "ConfigServiceType"):
""" name = service_class.name
Start configuration services for this node. if name in self.config_services:
raise CoreError(f"node({self.name}) already has service({name})")
self.config_services[name] = service_class(self)
:return: nothing def set_service_config(self, name: str, data: Dict[str, str]) -> None:
""" service = self.config_services.get(name)
for service in self.config_services: if service is None:
service.start() raise CoreError(f"node({self.name}) does not have service({name})")
service.set_config(data)
def makenodedir(self) -> None: def makenodedir(self) -> None:
""" """

View file

@ -1,8 +1,5 @@
import logging import logging
import os
from core import configservices
from core.configservice.manager import ConfigServiceManager
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.emudata import IpPrefixes, NodeOptions from core.emulator.emudata import IpPrefixes, NodeOptions
from core.emulator.enumerations import EventTypes, NodeTypes from core.emulator.enumerations import EventTypes, NodeTypes
@ -13,13 +10,13 @@ if __name__ == "__main__":
# setup basic network # setup basic network
prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16")
options = NodeOptions(model="nothing") options = NodeOptions(model="nothing")
# options.services = []
coreemu = CoreEmu() coreemu = CoreEmu()
session = coreemu.create_session() session = coreemu.create_session()
session.set_state(EventTypes.CONFIGURATION_STATE) session.set_state(EventTypes.CONFIGURATION_STATE)
switch = session.add_node(_type=NodeTypes.SWITCH) switch = session.add_node(_type=NodeTypes.SWITCH)
# node one # node one
options.config_services = ["DefaultRoute", "IPForward"]
node_one = session.add_node(options=options) node_one = session.add_node(options=options)
interface = prefixes.create_interface(node_one) interface = prefixes.create_interface(node_one)
session.add_link(node_one.id, switch.id, interface_one=interface) session.add_link(node_one.id, switch.id, interface_one=interface)
@ -29,14 +26,6 @@ if __name__ == "__main__":
interface = prefixes.create_interface(node_two) interface = prefixes.create_interface(node_two)
session.add_link(node_two.id, switch.id, interface_one=interface) session.add_link(node_two.id, switch.id, interface_one=interface)
# manager load config services
manager = ConfigServiceManager()
path = os.path.dirname(os.path.abspath(configservices.__file__))
manager.load(path)
manager.set_service(node_one, "DefaultRoute")
manager.set_service(node_one, "IPForward")
# start session and run services # start session and run services
session.instantiate() session.instantiate()