microovn

Microovn

Channel Revision Published Runs on
latest/edge 103 19 Mar 2026
Ubuntu 24.04
latest/edge 102 19 Mar 2026
Ubuntu 24.04
latest/edge 101 19 Mar 2026
Ubuntu 24.04
latest/edge 100 19 Mar 2026
Ubuntu 24.04
latest/edge 28 08 Nov 2025
Ubuntu 24.04
25.03/stable 52 05 Mar 2026
Ubuntu 24.04
25.03/stable 53 05 Mar 2026
Ubuntu 24.04
25.03/stable 51 05 Mar 2026
Ubuntu 24.04
25.03/stable 50 05 Mar 2026
Ubuntu 24.04
25.03/candidate 89 17 Mar 2026
Ubuntu 24.04
25.03/candidate 88 17 Mar 2026
Ubuntu 24.04
25.03/candidate 90 17 Mar 2026
Ubuntu 24.04
25.03/candidate 91 17 Mar 2026
Ubuntu 24.04
25.03/edge 91 06 Mar 2026
Ubuntu 24.04
25.03/edge 90 06 Mar 2026
Ubuntu 24.04
25.03/edge 89 06 Mar 2026
Ubuntu 24.04
25.03/edge 88 06 Mar 2026
Ubuntu 24.04
25.03/edge 23 02 Nov 2025
Ubuntu 24.04
24.03/stable 59 05 Mar 2026
Ubuntu 24.04
24.03/stable 40 05 Mar 2026
Ubuntu 24.04
24.03/stable 61 05 Mar 2026
Ubuntu 24.04
24.03/stable 60 05 Mar 2026
Ubuntu 24.04
24.03/stable 58 05 Mar 2026
Ubuntu 24.04
24.03/candidate 59 04 Feb 2026
Ubuntu 24.04
24.03/candidate 40 04 Feb 2026
Ubuntu 24.04
24.03/candidate 61 04 Feb 2026
Ubuntu 24.04
24.03/candidate 60 04 Feb 2026
Ubuntu 24.04
24.03/candidate 58 04 Feb 2026
Ubuntu 24.04
24.03/edge 95 17 Mar 2026
Ubuntu 24.04
24.03/edge 94 17 Mar 2026
Ubuntu 24.04
24.03/edge 93 17 Mar 2026
Ubuntu 24.04
24.03/edge 92 17 Mar 2026
Ubuntu 24.04
24.03/edge 40 02 Dec 2025
Ubuntu 24.04
juju deploy microovn --channel edge
Show information

Platform:

Ubuntu
24.04

"""
This is a charm library for the ovsdb interface. This contains two classes to
ease development of charms using this interface, one for provides and one for
requires.

The provides part of this takes the ovsdb connection strings from the microovn
environment file.

The requires part communicates with the relation data and gets these strings to
be easily returned and used for interaction with the ovsdb databases.
"""

# The unique Charmhub library identifier, never change it
LIBID = "599e7729d8cf403db3f6afb6d7c64c92"

# Increment this major API version when introducing breaking changes
LIBAPI = 0

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 1

ENV_FILE = "/var/snap/microovn/common/data/env/ovn.env"
CONNECT_ENV_NAME = "OVN_{0}_CONNECT"
CONNECT_STR_KEY = "db_{0}_connection_str"

from dataclasses import dataclass
import logging

from ops import CharmBase, StoredState, EventBase
from ops.framework import Object
from ops.model import (
    Application,
    ModelError,
    Relation,
    SecretNotFoundError,
    Unit,
)

logger = logging.getLogger(__name__)

@dataclass
class OVSDBConnectionString:
    """Class for storing the northbound and southbound connection strings"""
    nb: str
    sb: str


class OVSDBRequires(Object):
    _stored = StoredState()

    def __init__(
        self,
        charm: CharmBase,
        relation_name: str,
    ):
        super().__init__(charm, relation_name)
        self.charm = charm
        self.relation_name = relation_name

    """
    get_connection_strings takes the northbound and southbound connection strings
    from the relation data.

    it returns None on failure, and it returns a instance of
    OVSDBConnectionString containing both northbound and southbound strings
    """
    def get_connection_strings(self) -> OVSDBConnectionString:
        if not (relation := self.charm.model.get_relation(self.relation_name)):
            return None

        ovsdb_app_data = relation.data[relation.app]
        nb_connect = ovsdb_app_data.get(CONNECT_STR_KEY.format("nb"))
        sb_connect = ovsdb_app_data.get(CONNECT_STR_KEY.format("sb"))
        if nb_connect and sb_connect:
            return OVSDBConnectionString(nb=nb_connect, sb=sb_connect)
        else:
            return None

class OVSDBProvides(Object):
    _stored = StoredState()

    def __init__(
        self,
        charm: CharmBase,
        relation_name: str,
    ):
        super().__init__(charm, relation_name)
        self.charm = charm
        self.relation_name = relation_name
        self.framework.observe(
            self.charm.on[relation_name].relation_changed,
            self._on_ovsdb_relation_changed,
        )
        self.framework.observe(
            self.charm.on[relation_name].relation_created,
            self._on_ovsdb_relation_changed,
        )

    def _on_ovsdb_relation_changed(self, _: EventBase):
        self.update_relation_data()

    def update_relation_data(self):
        if not (self.charm.unit.is_leader() and self.charm._stored.in_cluster):
            return

        if not (relation := self.charm.model.get_relation(self.relation_name)):
            return

        connect_str = self.get_connection_strings()
        if connect_str:
            relation.data[self.charm.app][CONNECT_STR_KEY.format("nb")] = \
                connect_str.nb
            relation.data[self.charm.app][CONNECT_STR_KEY.format("sb")] = \
                connect_str.sb
            logger.info("connection strings updated")

    """
    get_connection_strings takes the northbound and southbound connection strings
    from the relation data.

    it returns None on failure, and it returns a instance of
    OVSDBConnectionString containing both northbound and southbound strings
    """
    def get_connection_strings(self) -> OVSDBConnectionString:
        nb_connect = None
        sb_connect = None
        try:
            with open(ENV_FILE, "r") as f:
                for line in f:
                    line = line.strip()
                    if line.startswith(CONNECT_ENV_NAME.format("NB")):
                        nb_connect = line.split("=", 1)[1].strip('"')
                    if line.startswith(CONNECT_ENV_NAME.format("SB")):
                        sb_connect = line.split("=", 1)[1].strip('"')
        except FileNotFoundError:
            logger.error(
                "OVN env file not found, is this unit in the microovn cluster?")
            raise FileNotFoundError("{0} not found".format(ENV_FILE))

        if nb_connect and sb_connect:
            return OVSDBConnectionString(nb=nb_connect, sb=sb_connect)
        else:
            return None