docs: adding initial documentation to help cover using config services
This commit is contained in:
parent
35a285daa2
commit
bd3e2f5d0e
3 changed files with 209 additions and 3 deletions
206
docs/configservices.md
Normal file
206
docs/configservices.md
Normal file
|
@ -0,0 +1,206 @@
|
|||
# CORE Config Services
|
||||
|
||||
* Table of Contents
|
||||
{:toc}
|
||||
|
||||
## Overview
|
||||
|
||||
Config services are a newer version of services for CORE, that leverage a
|
||||
templating engine, for more robust service file creation. They also
|
||||
have the power of configuration key/value pairs that values that can be
|
||||
defined and displayed within the GUI, to help further tweak a service,
|
||||
as needed.
|
||||
|
||||
CORE services are a convenience for creating reusable dynamic scripts
|
||||
to run on nodes, for carrying out specific task(s).
|
||||
|
||||
This boilds down to the following functions:
|
||||
* generating files the service will use, either directly for commands or for configuration
|
||||
* command(s) for starting a service
|
||||
* command(s) for validating a service
|
||||
* command(s) for stopping a service
|
||||
|
||||
Most CORE nodes will have a default set of services to run, associated with
|
||||
them. You can however customize the set of services a node will use. Or even
|
||||
further define a new node type within the GUI, with a set of services, that
|
||||
will allow quickly dragging and dropping that node type during creation.
|
||||
|
||||
## Available Services
|
||||
|
||||
| Service Group | Services |
|
||||
|---|---|
|
||||
|[BIRD](services/bird.md)|BGP, OSPF, RADV, RIP, Static|
|
||||
|[EMANE](services/emane.md)|Transport Service|
|
||||
|[FRR](services/frr.md)|BABEL, BGP, OSPFv2, OSPFv3, PIMD, RIP, RIPNG, Zebra|
|
||||
|[NRL](services/nrl.md)|arouted, MGEN Sink, MGEN Actor, NHDP, OLSR, OLSRORG, OLSRv2, SMF|
|
||||
|[Quagga](services/quagga.md)|BABEL, BGP, OSPFv2, OSPFv3, OSPFv3 MDR, RIP, RIPNG, XPIMD, Zebra|
|
||||
|[SDN](services/sdn.md)|OVS, RYU|
|
||||
|[Security](services/security.md)|Firewall, IPsec, NAT, VPN Client, VPN Server|
|
||||
|[Utility](services/utility.md)|ATD, Routing Utils, DHCP, FTP, IP Forward, PCAP, RADVD, SSF, UCARP|
|
||||
|[XORP](services/xorp.md)|BGP, OLSR, OSPFv2, OSPFv3, PIMSM4, PIMSM6, RIP, RIPNG, Router Manager|
|
||||
|
||||
## Node Types and Default Services
|
||||
|
||||
Here are the default node types and their services:
|
||||
|
||||
| Node Type | Services |
|
||||
|---|---|
|
||||
| *router* | zebra, OSFPv2, OSPFv3, and IPForward services for IGP link-state routing. |
|
||||
| *PC* | DefaultRoute service for having a default route when connected directly to a router. |
|
||||
| *mdr* | zebra, OSPFv3MDR, and IPForward services for wireless-optimized MANET Designated Router routing. |
|
||||
| *prouter* | a physical router, having the same default services as the *router* node type; for incorporating Linux testbed machines into an emulation. |
|
||||
|
||||
Configuration files can be automatically generated by each service. For
|
||||
example, CORE automatically generates routing protocol configuration for the
|
||||
router nodes in order to simplify the creation of virtual networks.
|
||||
|
||||
To change the services associated with a node, double-click on the node to
|
||||
invoke its configuration dialog and click on the *Services...* button,
|
||||
or right-click a node a choose *Services...* from the menu.
|
||||
Services are enabled or disabled by clicking on their names. The button next to
|
||||
each service name allows you to customize all aspects of this service for this
|
||||
node. For example, special route redistribution commands could be inserted in
|
||||
to the Quagga routing configuration associated with the zebra service.
|
||||
|
||||
To change the default services associated with a node type, use the Node Types
|
||||
dialog available from the *Edit* button at the end of the Layer-3 nodes
|
||||
toolbar, or choose *Node types...* from the *Session* menu. Note that
|
||||
any new services selected are not applied to existing nodes if the nodes have
|
||||
been customized.
|
||||
|
||||
The node types are saved in the GUI config file **~/.coregui/config.yaml**.
|
||||
Keep this in mind when changing the default services for
|
||||
existing node types; it may be better to simply create a new node type. It is
|
||||
recommended that you do not change the default built-in node types.
|
||||
|
||||
## New Services
|
||||
|
||||
Services can save time required to configure nodes, especially if a number
|
||||
of nodes require similar configuration procedures. New services can be
|
||||
introduced to automate tasks.
|
||||
|
||||
### Creating New Services
|
||||
|
||||
1. Modify the example service shown below
|
||||
to do what you want. It could generate config/script files, mount per-node
|
||||
directories, start processes/scripts, etc. Your file can define one or more
|
||||
classes to be imported. You can create multiple Python files that will be imported.
|
||||
|
||||
2. Put these files in a directory such as ~/.coregui/custom_services
|
||||
Note that the last component of this directory name **myservices** should not
|
||||
be named something like **services** which conflicts with an existing module.
|
||||
|
||||
3. Add a **custom_config_services_dir = ~/.coregui/custom_services** entry to the
|
||||
/etc/core/core.conf file.
|
||||
|
||||
**NOTE:**
|
||||
The directory name used in **custom_services_dir** should be unique and
|
||||
should not correspond to
|
||||
any existing Python module name. For example, don't use the name **subprocess**
|
||||
or **services**.
|
||||
|
||||
4. Restart the CORE daemon (core-daemon). Any import errors (Python syntax)
|
||||
should be displayed in the terminal (or service log, like journalctl).
|
||||
|
||||
5. Start using your custom service on your nodes. You can create a new node
|
||||
type that uses your service, or change the default services for an existing
|
||||
node type, or change individual nodes. .
|
||||
|
||||
### Example Custom Service
|
||||
|
||||
Below is the skeleton for a custom service with some documentation. Most
|
||||
people would likely only setup the required class variables **(name/group)**.
|
||||
Then define the **files** to generate and implement the
|
||||
**get_text_template** function to dynamically create the files wanted. Finally,
|
||||
the **startup** commands would be supplied, which typically tend to be
|
||||
running the shell files generated.
|
||||
|
||||
```python
|
||||
from typing import Dict, List
|
||||
|
||||
from core.config import Configuration
|
||||
from core.configservice.base import ConfigService, ConfigServiceMode, ShadowDir
|
||||
from core.emulator.enumerations import ConfigDataTypes
|
||||
|
||||
# class that subclasses ConfigService
|
||||
class ExampleService(ConfigService):
|
||||
# unique name for your service within CORE
|
||||
name: str = "Example"
|
||||
# the group your service is associated with, used for display in GUI
|
||||
group: str = "ExampleGroup"
|
||||
# directories that the service should shadow mount, hiding the system directory
|
||||
directories: List[str] = [
|
||||
"/usr/local/core",
|
||||
]
|
||||
# files that this service should generate, defaults to nodes home directory
|
||||
# or can provide an absolute path to a mounted directory
|
||||
files: List[str] = [
|
||||
"example-start.sh",
|
||||
"/usr/local/core/file1",
|
||||
]
|
||||
# executables that should exist on path, that this service depends on
|
||||
executables: List[str] = []
|
||||
# other services that this service depends on, can be used to define service start order
|
||||
dependencies: List[str] = []
|
||||
# commands to run to start this service
|
||||
startup: List[str] = []
|
||||
# commands to run to validate this service
|
||||
validate: List[str] = []
|
||||
# commands to run to stop this service
|
||||
shutdown: List[str] = []
|
||||
# validation mode, blocking, non-blocking, and timer
|
||||
validation_mode: ConfigServiceMode = ConfigServiceMode.BLOCKING
|
||||
# configurable values that this service can use, for file generation
|
||||
default_configs: List[Configuration] = [
|
||||
Configuration(id="value1", type=ConfigDataTypes.STRING, label="Text"),
|
||||
Configuration(id="value2", type=ConfigDataTypes.BOOL, label="Boolean"),
|
||||
Configuration(
|
||||
id="value3",
|
||||
type=ConfigDataTypes.STRING,
|
||||
label="Multiple Choice",
|
||||
options=["value1", "value2", "value3"],
|
||||
),
|
||||
]
|
||||
# sets of values to set for the configuration defined above, can be used to
|
||||
# provide convenient sets of values to typically use
|
||||
modes: Dict[str, Dict[str, str]] = {
|
||||
"mode1": {"value1": "value1", "value2": "0", "value3": "value2"},
|
||||
"mode2": {"value1": "value2", "value2": "1", "value3": "value3"},
|
||||
"mode3": {"value1": "value3", "value2": "0", "value3": "value1"},
|
||||
}
|
||||
# defines directories that this service can help shadow within a node
|
||||
shadow_directories: List[ShadowDir] = [
|
||||
ShadowDir(path="/user/local/core", src="/opt/core")
|
||||
]
|
||||
|
||||
def get_text_template(self, name: str) -> str:
|
||||
if name == "example-start.sh":
|
||||
return """
|
||||
# sample script 1
|
||||
# node id(${node.id}) name(${node.name})
|
||||
# config: ${config}
|
||||
echo hello
|
||||
"""
|
||||
```
|
||||
|
||||
#### Validation Mode
|
||||
|
||||
Validation modes are used to determine if a service has started up successfully.
|
||||
|
||||
* blocking - startup commands are expected to run til completion and return 0 exit code
|
||||
* non-blocking - startup commands are ran, but do not wait for completion
|
||||
* timer - startup commands are ran, and an arbitrary amount of time is waited to consider started
|
||||
|
||||
#### Shadow Directories
|
||||
|
||||
Shadow directories provide a convenience for copying a directory and the files within
|
||||
it to a nodes home directory, to allow a unique set of per node files.
|
||||
|
||||
* `ShadowDir(path="/user/local/core")` - copies files at the given location into the node
|
||||
* `ShadowDir(path="/user/local/core", src="/opt/core")` - copies files to the given location,
|
||||
but sourced from the provided location
|
||||
* `ShadowDir(path="/user/local/core", templates=True)` - copies files and treats them as
|
||||
templates for generation
|
||||
* `ShadowDir(path="/user/local/core", has_node_paths=True)` - copies files from the given
|
||||
location, and looks for unique node names directories within it, using a directory named
|
||||
default, when not preset
|
|
@ -29,6 +29,7 @@ networking scenarios, security studies, and increasing the size of physical test
|
|||
|[gRPC API](grpc.md)|Covers how control core using gRPC|
|
||||
|[Distributed](distributed.md)|Details for running CORE across multiple servers|
|
||||
|[Control Network](ctrlnet.md)|How to use control networks to communicate with nodes from host|
|
||||
|[Config Services](configservices.md)|Overview of provided config services and creating custom ones|
|
||||
|[Services](services.md)|Overview of provided services and creating custom ones|
|
||||
|[EMANE](emane.md)|Overview of EMANE integration and integrating custom EMANE models|
|
||||
|[Performance](performance.md)|Notes on performance when using CORE|
|
||||
|
|
|
@ -149,12 +149,11 @@ ideas for a service before adding a new service type.
|
|||
to do what you want. It could generate config/script files, mount per-node
|
||||
directories, start processes/scripts, etc. sample.py is a Python file that
|
||||
defines one or more classes to be imported. You can create multiple Python
|
||||
files that will be imported. Add any new filenames to the __init__.py file.
|
||||
files that will be imported.
|
||||
|
||||
2. Put these files in a directory such as /home/username/.core/myservices
|
||||
Note that the last component of this directory name **myservices** should not
|
||||
be named something like **services** which conflicts with an existing Python
|
||||
name (the syntax 'from myservices import *' is used).
|
||||
be named something like **services** which conflicts with an existing module.
|
||||
|
||||
3. Add a **custom_services_dir = /home/username/.core/myservices** entry to the
|
||||
/etc/core/core.conf file.
|
||||
|
|
Loading…
Reference in a new issue