IP Router Interface
- Canonical Telco
Channel | Revision | Published | Runs on |
---|---|---|---|
latest/edge | 2 | 20 Oct 2023 |
juju deploy ip-router-interface --channel edge
Deploy universal operators easily with Juju, the Universal Operator Lifecycle Manager.
Platform:
charms.ip_router_interface.v0.ip_router_interface
-
- Last updated 19 Oct 2023
- Revision Library version 0.2
Library for the ip-router integration
This library contains the Requires and Provides classes for interactions through the ip-router interface
Getting Started
From a charm directory, fetch the library using charmcraft
:
charmcraft fetch-lib charms.ip_router_interface.v0.ip_router_interface
Provider charm
This example provider charm is all we need to listen to ip-router requirer requests. The ip-router provider fulfills the routing function for multiple charms that are requirers of the ip-router interface. For that reason, this charm will continuously track and update all of the connected requirers and the networks and routes they've requested, which it does in a routing table. As new charms are connected and disconnected to the relation, this routing table is automatically adds and removes the dependent networks.
The library handles the listening and synchronization for all of the ip-router network requests internally, which means as the charm author you don't need to worry about any of the business logic of validating or orchestrating the relation network.
You can also listen to the routing_table_updated
event that is emitted after the
tables are synced.
import logging, json
import ops
from charms.ip_router_interface.v0.ip_router_interface import *
class SimpleIPRouteProviderCharm(ops.CharmBase):
def __init__(self, *args):
super().__init__(*args)
self.RouterProvider = RouterProvides(charm=self)
self.framework.observe(self.on.install, self._on_install)
self.framework.observe(self.RouterProvider.on.routing_table_updated, self._routing_table_updated)
self.framework.observe(self.on.get_routing_table_action, self._action_get_routing_table)
def _on_install(self, event: ops.InstallEvent):
self.unit.status = ops.ActiveStatus("Ready to Provide")
def _routing_table_updated(self, event: RoutingTableUpdatedEvent):
routing_table = event.routing_table
# Process the networks however you like
implement_networks(all_networks)
def _action_get_routing_table(self, event: ops.ActionEvent):
all_networks = self.RouterProvider.get_flattened_routing_table()
event.set_results({"msg": json.dumps(all_networks)})
if __name__ == "__main__": # pragma: nocover
ops.main(SimpleIPRouteProviderCharm) # type: ignore
Requirer charm
This example requirer charm shows the two available actions as a host in the network:
- get the latest list of all networks available from the provider
- request a network to be assigned to the requirer charm
The ip-router requirer allows a foolproof, typechecked, secure and safe way to interact with the router that handles validation and format of the network request, so you can focus on more important things. The library also provides a way to list out all of the available networks. This list is not cached, and comes directly from the provider.
import logging, json
import ops
from charms.ip_router_interface.v0.ip_router_interface import *
class SimpleIPRouteRequirerCharm(ops.CharmBase):
def __init__(self, *args):
super().__init__(*args)
self.RouterRequirer = RouterRequires(charm=self)
self.framework.observe(self.on.install, self._on_install)
self.framework.observe(self.on.ip_router_relation_joined, self._on_relation_joined)
self.framework.observe(self.RouterProvider.on.routing_table_updated, self._routing_table_updated)
self.framework.observe(self.on.get_all_networks_action, self._action_get_all_networks)
self.framework.observe(self.on.request_network_action, self._action_request_network)
def _on_install(self, event: ops.InstallEvent):
self.unit.status = ops.ActiveStatus("Ready to Provide")
def _on_relation_joined(self, event: ops.RelationJoinedEvent):
self.unit.status = ops.ActiveStatus("Ready to Require")
def _routing_table_updated(self, event: RoutingTableUpdatedEvent):
# Get and process all of the available networks when they're updated
all_networks = self.RouterRequirer.get_all_networks()
def _action_get_all_networks(self, event: ops.ActionEvent):
# Get and process all of the available networks any time you like
all_networks = self.RouterRequirer.get_all_networks()
event.set_results({"msg": json.dumps(all_networks)})
def _action_request_network(self, event: ops.ActionEvent):
# Request a new network as required in the required format
self.RouterRequirer.request_network(event.params["network"])
event.set_results({"msg": "ok"})
if __name__ == "__main__": # pragma: nocover
ops.main.main(SimpleIPRouteRequirerCharm) # type: ignore
You can relate both charms by running:
juju integrate <ip-router provider charm> <ip-router requirer charm>
Index
class RoutingTableUpdatedEvent
Description
Charm event for when a host registers a route to an existing interface in the router None
Methods
RoutingTableUpdatedEvent. __init__( self , handle , routing_table )
RoutingTableUpdatedEvent. snapshot( self )
RoutingTableUpdatedEvent. restore( self , snapshot )
class RouterProviderCharmEvents
class RouterRequirerCharmEvents
class RouterProvides
This class is used to manage the routing table of the router provider.
Attributes
Description
It's capabilities are to:
- Build a Routing Table from all of the databags of the requirers with their declared networks.
- Synchronize the databags of all requiring units with the aforementioned routing table.
- Send events indicating a change in this table.
Methods
RouterProvides. __init__( self , charm: CharmBase , relationship_name: str )
RouterProvides. get_routing_table( self )
Description
Build the routing table from all of the related databags. Relations that don't have missing or invalid network requests will be ignored.
RouterProvides. get_flattened_routing_table( self )
Returns
A list of objects of type Network
Description
Returns a read-only routing table that's flattened to fit the specification. The routing table is in the form of { app1_name: list_of_networks_1, app2_name: list_of_networks_2, ... }
A flattened table looks like [ *list_of_networks_1, *list_of_networks_2, ... ]
class RouterRequires
ip-router requirer class to be instantiated by charms that require routing
Attributes
Description
This class provides methods to request a new network, and read the available network from the router providers. These should be used exclusively to interact with the relation.
Methods
RouterRequires. __init__( self , charm: CharmBase , relationship_name: str )
RouterRequires. request_network( self , networks , custom_network_name: str )
Requests a new network interface from the ip-router provider
Description
The interfaces must be valid according to _network_is_valid
. Multiple
calls to this function will replace the previously requested networks,
so all of the networks required must be given with each call.
Arguments:
networks:
A list containing the desired networks of the type Network
.
custom_network_name:
A string to use as the name of the network. Defaults to the relation
name.
Raises: RuntimeError: No ip-router relation exists yet or validation of one or more of the networks failed.
RouterRequires. get_all_networks( self )
Fetches combined routing tables made available by ip-router providers
Returns
A list of objects of type Network
. This list contains networks
from all ip-router providers that are integrated with the charm.