The ng-cdi intent deployer is a service for translating intents into configuration changes to a network.
We currently support three main methods of declaring intents:
- Dialogflow: Intents are sourced from the dialogflow NLP platform. Dialogflow submits intents to the service using a webhook.
- NILE: NILE intents are submitted to the service using the
/deploy
route. - REST: The service generates api routes for each intent we can handle.
You can view the api documentation at /docs
ngcdi-intent-tests.zip contains the dialogflow agent. Once you have a dialogflow agent set up, you can import the intents from there.
For connecting dialogflow and the intent deployer, I recommend using ngrok or similar.
Using ngrok: ngrok http <port>
Then place the printed url into the fulfillment/webhook section of dialogflow in
the format: <url>/dialogflow_webook
and fill in the 'basic auth' parameters
with the values from WEBHOOK_USER
and WEBHOOK_PASS
respectively.
You also need to set up a telegram bot and set the token in the local env file and in dialogflow under integrations.
Make sure that 'Enable webhook call for this intent' is enabled on the intents in dialogflow.
You need a running ONOS instance for the intent deployer to work with, in the case the ONOS instance is running on a remote server, you can use the following SSH command to set up port forwarding:
ssh -N -L 8181:localhost:8181 -L 5000:localhost:5000 \
-L 172.17.0.1:8181:localhost:8181 -L 172.17.0.1:5000:localhost:5000 \
<onos server>
The 127.17.0.1
binding here is to expose the service inside the docker
network.
The following env vars must be set (just generate a secure password):
WEBHOOK_PASS=<dialogflow/prometheus webhook http auth pass>
The following env vars can be set:
TELEGRAM_TOKEN=<telegram token for status updates>
ONOS_API_URL=<url of the onos api, defaults to https://onos.demo.ng-cdi.com/onos/v1/>
NGCDI_URL=<url of the 'reroute' api, defaults to https://api.demo.ng-cdi.com/api/>
For a local instance of https://github.com/ng-cdi/demo-intents, you should probably have the following env vars:
export ONOS_API_URL=http://localhost:8181/onos/v1/
export NGCDI_URL=http://localhost:5000/api
To run the intent deployer, you can run poetry run uvicorn app:app
You can get poetry from https://python-poetry.org/
The compose file is set up and just needs the environment section filling in.
You'll need the port forwarding set up and exposed inside the docker network. YMMV with this on non linux machines.
Run with docker-compose up
alerts/
: Contains definitions of alert handlers, these are triggered by prometheus alertmanager.batfish/
: Contains the batfish topology.intent_deployer/
: Internal stuff, refer to each file for details.intents/
: Contains definitions of each intent.neat_integration/
: Code and models for testing configuration changes using NEAT.webhook/
: Types and models relevant to Dialogflow.
The application automatically collects intents defined inside of intents/
,
python decorators are used to register these.
@register_nile_handler(<name>)
declares a function to extract relevant information from a NILE intent.@register_dialogflow_handler(<name>)
declares a function to extract relevant information from a dialogflow intent. This is passed a python dictionary with string keys (dict[str, Any]
). Thename
parameter to the decorator should be the same as the corresponding dialogflow intent name.
The callbacks for the above decorators should return an object describing the intent, a good way of doing this is using a pydantic object like so:
from pydantic import BaseModel
class ForwardIntent(BaseModel):
src: str
dst: str
path: list[str]
ForwardIntent(src="h1", dst="h2", path=["s1", "s2"])
The intent executor is declared to handle the intent parsed by the nile handler/ dialogflow handler functions:
@register_intent_executor(<intent type>)
async def handle_intent(ctx: Context, intent: <intent type>):
# ...
The Context
type here contains information and methods to assist with the
interactivity of the intent deployment. Context
has a single method currently:
confirm_if_needed(msg, callback)
, in a dialogflow context this is used to
display a message and await confirmation from the user, in any other context the
callback is executed immediately.
In a dialogflow context the passed Context
will be an instance of
DialogflowContext
which contains helper methods for building the initial
response, waiting for confirmation, and .get_notifier
which returns a
Notifier
object, which can be used to send followup and unprompted messages.
The .confirm_if_needed
method of Context
objects can be used to confirm with
the user if something should happen. Currently this only does anything with
dialogflow contexts, for NILE/REST contexts we assume confirmation and execute
the callback immediately.
The .confirm_if_needed
method can only be used for the first confirmation, if
you need any more you should test if the context is a dialogflow context then
fetch the notifier to send another message. You can use the
.wait_for_confirmation
method as many times as needed.
An example of using the notifier to send followup messages:
if isinstance(ctx, DialogflowContext):
notifier = ctx.get_notifier()
if notifier is not None:
await notifier.send("Hello")