NorFab Inventory¤
NorFab comes with Simple Inventory Datastore (SID) hosted by broker, allowing workers to source inventory data from broker.
NorFab inventory separated in sections, each responsible for configuring different aspects of the system.
broker: # (1)!
endpoint: "tcp://127.0.0.1:5555" # (2)!
workers: # (3)!
nornir-*: # (4)!
- nornir/common.yaml
nornir-worker-1: # (5)!
- nornir/nornir-worker-1.yaml
topology: # (6)!
broker: True # (7)!
workers: # (8)!
- nornir-worker-1
logging: # (9)!
handlers:
terminal:
level: WARNING
file:
level: INFO
- Broker configuration inventory section
- URL to listen for connections on -
localhost
port5555
in this case - Workers configuration inventory section
- glob pattern that will match all workers with
nornir-
in the name and mapcommon.yaml
file content for each of them - Worker definition to map inventory file to a specific worker that has name
nornir-worker-1
- Topology section to define what components to run
- Start broker process
- List of workers names to start processes for
- Logging configuration section
Broker Inventory Section¤
Broker inventory must have broker_endpoint
parameter defined for workers and clients to identify how connect with broker, and for broker itself to identify where to listen for connections.
# broker settings
broker:
endpoint: "tcp://127.0.0.1:5555"
shared_key: "5z1:yW}]n?UXhGmz+5CeHN1>:S9k!eCh6JyIhJqO"
In addition these parameters are supported
shared_key
- broker encryption shared key may or may not be needed depending of type of the setup you are running, in case if all components - broker, client and workers run on same machine, configuringshared_key
parameter is options, asnfapi
is smart enough to auto-configure all workers and client with correct broker shared key. In case if broker and workers with clients are distributed i.e. running in separate containers or on separate machines,share_key
parameter must be configured on all workers and clients to match shared key used by broker.
Workers Inventory Section¤
To understand how Simple Inventory Datastore serves workers inventory it is good to know that each worker has a unique name to identify it.
With that in mind, the goal is to map inventory data to individual worker by its name.
For example, let's pretend that worker name is nornir-worker-1
and we have common.yaml
and nornir-worker-1.yaml
files with inventory data that we need to provide worker with.
To do the mapping between worker name and inventory files we can put this in NorFab inventory (inventory.yaml
) file:
workers:
nornir-*:
- nornir/common.yaml
nornir-worker-1:
- nornir/nornir-worker-1.yaml
Where files structure would look like this:
└───rootfolder
│ inventory.yaml
│
└───nornir
common.yaml
nornir-worker-1.yaml
As you can see, inventory.yaml
file contains workers
section with a dictionary keyed by glob patterns to match against workers' names, once worker name matched by the pattern, all items in the list underneaths that pattern being loaded and recursively merged. As such, process continues until all patterns evaluated. Final output of the process is a combined inventory data of all the matched files.
The recursive logic of combining inventory data files is pretty straightforward - each next data file merged into the previous data file overriding the overlapping values.
The glob pattern matching logic allows be as specific as required and map specific files to individual workers or to map single data file to multiple workers or map multiple files to multiple workers, all combinations supported.
For example, we have a group of two workers with names netbox-wroker-1.1
and
netbox-worker-1.2
and we want to map netbox_common.yaml
to both of the workers,
in that case NorFab inventory (inventory.yaml
) file could have this content:
workers:
netbox-worker-1.*:
- nornir/netbox_common.yaml
Where files structure would look like this:
└───rootfolder
│ inventory.yaml
│
└───netbox
netbox_common.yaml
Both workers will be served with netbox_common.yaml
file content as an inventory data.
Workers Inventory Parameters¤
Workers inventory can contain these common parameters:
service
- name of the service this worker belongs to
Sample worker base inventory:
service: nornir
The rest of the inventory data is worker specific.
Topology Inventory Section¤
Topology section of NorFab inventory identifies the components that need to be started on the given node.
Logging Inventory Section¤
Logging inventory section allows to configure logging parameters such file retention option, logging to remote hosts, logging levels etc.
Hooks Section¤
Hooks section allows to configure a list of functions to run during NorFab execution lifespan events.
Supported attach points:
startup
- list of functions to run right after NorFab nfapi started broker and worker process and fully initialized. Startup hook function must acceptnorfab
object as a single argument.exit
- list of functions to run right before NorFab nfapi initiates exit sequence. Exit hook function must acceptnorfab
object as a single argument.
Each hook defined as a dictionary that can contain these keys:
function
- Python import path for hook functionattachpoint
- one of the attach points indicating when to run hook function e.g.startup
args
- optional list of function positional argumentskwargs
- optional dictionary of function key-word arguments
Sample hooks definition:
hooks:
- attachpoint: startup
function: "hooks.functions.do_on_startup"
args: []
kwargs: {}
description: "Function to run on startup"
- attachpoint: exit
function: "hooks.functions.do_on_exit"
args: []
kwargs: {}
description: "Function to run on startup"
Where hook functions are:
def do_on_startup(norfab):
print("Startup hook executed")
def do_on_exit(norfab):
print("Exit hook executed")
Function import path is a dot separated path used to import module file that contains hook functions, where individual function name is a last item in dot separated path definition. For example hooks.functions.do_on_startup
path is equivalent of running Python import from hooks.functions import do_on_startup
.
Jinja2 Support¤
Starting with version 0.3.0 NorFab supports Jinja2 syntax rendering of inventory files, in addition, env
dictionary variable available to source environment variables:
logging:
handlers:
terminal:
level: {{ env.get("TERMINAL_LOGGING_LEVEL", "WARNING") }}
file:
level: {{ env.get("FILE_LOGGING_LEVEL", "INFO") }}
Above example demonstrates how terminal and file logging level can be sourced from environment using Jinja2 syntax.
All workers inventory files also passed through Jinja2 renderer with access to env
dictionary variable:
defaults:
username: {{ env.get("NORNIR_USERNAME", "nornir") }}
password: {{ env.get("NORNIR_PASSWORD", "password" ) }}
env
variable passed onto Jinja2 context as a dictionary that contains environment variables keys and values supporting all Jinja2 dictionary access operations:
defaults:
username: {{ env["NORNIR_USERNAME"] }}
password: {{ env.NORNIR_PASSWORD }}
port: {{ env.get("NORNIR_PORT", 22) }}
Loading Inventory from Dictionary¤
By default NorFab supports loading inventory from inventory.yaml
file together with workers
section items referring to a list of OS paths to YAML files with workers inventory data. As an alternative it is possible to load full NorFab and its workers inventory from dictionary, this can be useful when working with NorFab Python API directly:
from norfab.core.nfapi import NorFab
data = {
"broker": {
"endpoint": "tcp://127.0.0.1:5555",
"shared_key": "5z1:yW}]n?UXhGmz+5CeHN1>:S9k!eCh6JyIhJqO",
},
"workers": {
"nornir-*": [
{
"service": "nornir",
"watchdog_interval": 30,
"runner": {
"plugin": "RetryRunner",
"options": {
"num_workers": 100,
"num_connectors": 10,
}
}
}
],
"nornir-worker-1*": ["nornir/nornir-worker-1.yaml"],
"nornir-worker-2": [
"nornir/nornir-worker-2.yaml",
"nornir/nornir-worker-2-extra.yaml",
],
},
"topology": {
"broker": True,
"workers": [
"nornir-worker-1",
"nornir-worker-2",
],
},
}
if __name__ == "__main__":
nf = NorFab(inventory_data=data, base_dir="./norfab/")
nf.start()
client = nf.make_client()
job_result = client.run_job("nornir", "get_nornir_hosts")
print(job_result)
nf.destroy()
In above example, data
dictionary contains complete NorFab inventory and passed onto NorFab
object together with base_dir
argument to inform NorFab where to search for inventory YAML files, for example "nornir/nornir-worker-2.yaml"
file will be searched within this path "./norfab/nornir/nornir-worker-2.yaml"
since ./norfab/
is a base directory. Base directory argument is optional and will be automatically set by NorFab to current directory.