Skip to content

Commit

Permalink
chore: use multus lib 0.16
Browse files Browse the repository at this point in the history
Signed-off-by: guillaume <guillaume.belanger27@gmail.com>
  • Loading branch information
gruyaume committed Sep 5, 2024
1 parent 9c2ae0d commit 39d7230
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 72 deletions.
97 changes: 36 additions & 61 deletions lib/charms/kubernetes_charm_libraries/v0/multus.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def _on_config_changed(self, event: EventBase):
import logging
from dataclasses import asdict, dataclass
from json.decoder import JSONDecodeError
from typing import Callable, List, Optional, Union
from typing import List, Optional, Union

import httpx
from lightkube.core.client import Client
Expand All @@ -115,8 +115,6 @@ def _on_config_changed(self, event: EventBase):
from lightkube.resources.apps_v1 import StatefulSet
from lightkube.resources.core_v1 import Pod
from lightkube.types import PatchType
from ops.charm import CharmBase, RemoveEvent
from ops.framework import BoundEvent, Object

# The unique Charmhub library identifier, never change it
LIBID = "75283550e3474e7b8b5b7724d345e3c2"
Expand All @@ -126,7 +124,7 @@ def _on_config_changed(self, event: EventBase):

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


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -430,7 +428,7 @@ def unpatch_statefulset(
]
)
)
container.securityContext.privileged = False
container.securityContext.privileged = False # type: ignore[reportOptionalMemberAccess]
statefulset_delta = StatefulSet(
spec=StatefulSetSpec(
selector=statefulset.spec.selector, # type: ignore[union-attr]
Expand Down Expand Up @@ -602,57 +600,49 @@ def multus_is_available(self) -> bool:
return True


class KubernetesMultusCharmLib(Object):
class KubernetesMultusCharmLib:
"""Class to be instantiated by charms requiring Multus networking."""

def __init__(
self,
charm: CharmBase,
network_attachment_definitions_func: Callable[
[], list[NetworkAttachmentDefinition]
],
network_annotations_func: Callable[[], list[NetworkAnnotation]],
network_attachment_definitions: List[NetworkAttachmentDefinition],
network_annotations: List[NetworkAnnotation],
namespace: str,
statefulset_name: str,
pod_name: str,
container_name: str,
refresh_event: BoundEvent,
cap_net_admin: bool = False,
privileged: bool = False,
):
"""Constructor for the KubernetesMultusCharmLib.
Args:
charm: Charm object
network_attachment_definitions_func: A callable to a function returning a list of
`NetworkAttachmentDefinition` to be created.
network_annotations_func: A callable to a function returning a list
of `NetworkAnnotation` to be added to the container.
network_attachment_definitions: list of `NetworkAttachmentDefinition` to be created.
network_annotations: List of `NetworkAnnotation` to be added to the container.
namespace: Kubernetes namespace
statefulset_name: Statefulset name
pod_name: Pod name
container_name: Container name
cap_net_admin: Container requires NET_ADMIN capability
privileged: Container requires privileged security context
refresh_event: A BoundEvent which will be observed
to configure_multus (e.g. NadConfigChangedEvent).
"""
super().__init__(charm, "kubernetes-multus")
self.kubernetes = KubernetesClient(namespace=self.model.name)
self.network_attachment_definitions_func = network_attachment_definitions_func
self.network_annotations_func = network_annotations_func
self.namespace = namespace
self.statefulset_name = statefulset_name
self.pod_name = pod_name
self.kubernetes = KubernetesClient(namespace=self.namespace)
self.network_attachment_definitions = network_attachment_definitions
self.network_annotations = network_annotations
self.container_name = container_name
self.cap_net_admin = cap_net_admin
self.privileged = privileged
# Apply custom events
self.framework.observe(refresh_event, self._configure_multus)
self.framework.observe(charm.on.remove, self._on_remove)

def _configure_multus(self, event: BoundEvent) -> None:
"""Creates network attachment definitions and patches statefulset.

Args:
event: EventBase
"""
def configure(self) -> None:
"""Creates network attachment definitions and patches statefulset."""
self._configure_network_attachment_definitions()
if not self._statefulset_is_patched():
self.kubernetes.patch_statefulset(
name=self.model.app.name,
network_annotations=self.network_annotations_func(),
name=self.statefulset_name,
network_annotations=self.network_annotations,
container_name=self.container_name,
cap_net_admin=self.cap_net_admin,
privileged=self.privileged,
Expand All @@ -667,7 +657,7 @@ def _network_attachment_definition_created_by_charm(
return False
if "app.juju.is/created-by" not in labels:
return False
if labels["app.juju.is/created-by"] != self.model.app.name:
if labels["app.juju.is/created-by"] != self.statefulset_name:
return False
return True

Expand All @@ -683,9 +673,7 @@ def _configure_network_attachment_definitions(self):
3. Detects the NAD config changes and triggers pod restart
if any there is any modification in existing NADs
"""
network_attachment_definitions_to_create = (
self.network_attachment_definitions_func()
)
network_attachment_definitions_to_create = self.network_attachment_definitions
nad_config_changed = False
for (
existing_network_attachment_definition
Expand Down Expand Up @@ -725,7 +713,7 @@ def _configure_network_attachment_definitions(self):

def _network_attachment_definitions_are_created(self) -> bool:
"""Returns whether all network attachment definitions are created."""
for network_attachment_definition in self.network_attachment_definitions_func():
for network_attachment_definition in self.network_attachment_definitions:
if not self.kubernetes.network_attachment_definition_is_created(
network_attachment_definition=network_attachment_definition
):
Expand All @@ -735,8 +723,8 @@ def _network_attachment_definitions_are_created(self) -> bool:
def _statefulset_is_patched(self) -> bool:
"""Returns whether statefuset is patched with network annotations and capabilities."""
return self.kubernetes.statefulset_is_patched(
name=self.model.app.name,
network_annotations=self.network_annotations_func(),
name=self.statefulset_name,
network_annotations=self.network_annotations,
container_name=self.container_name,
cap_net_admin=self.cap_net_admin,
privileged=self.privileged,
Expand All @@ -745,8 +733,8 @@ def _statefulset_is_patched(self) -> bool:
def _pod_is_ready(self) -> bool:
"""Returns whether pod is ready with network annotations and capabilities."""
return self.kubernetes.pod_is_ready(
pod_name=self._pod,
network_annotations=self.network_annotations_func(),
pod_name=self.pod_name,
network_annotations=self.network_annotations,
container_name=self.container_name,
cap_net_admin=self.cap_net_admin,
privileged=self.privileged,
Expand All @@ -767,26 +755,13 @@ def is_ready(self) -> bool:
pod_is_ready = self._pod_is_ready()
return nad_are_created and satefulset_is_patched and pod_is_ready

@property
def _pod(self) -> str:
"""Name of the unit's pod.
Returns:
str: A string containing the name of the current unit's pod.
"""
return "-".join(self.model.unit.name.rsplit("/", 1))

def _on_remove(self, event: RemoveEvent) -> None:
"""Deletes network attachment definitions and removes patch.
Args:
event: RemoveEvent
"""
def remove(self) -> None:
"""Deletes network attachment definitions and removes patch."""
self.kubernetes.unpatch_statefulset(
name=self.model.app.name,
name=self.statefulset_name,
container_name=self.container_name,
)
for network_attachment_definition in self.network_attachment_definitions_func():
for network_attachment_definition in self.network_attachment_definitions:
if self.kubernetes.network_attachment_definition_is_created(
network_attachment_definition=network_attachment_definition
):
Expand All @@ -796,7 +771,7 @@ def _on_remove(self, event: RemoveEvent) -> None:

def delete_pod(self) -> None:
"""Delete the pod."""
self.kubernetes.delete_pod(self._pod)
self.kubernetes.delete_pod(self.pod_name)

def multus_is_available(self) -> bool:
"""Check whether Multus is enabled leveraging existence of NAD custom resource.
Expand Down
18 changes: 7 additions & 11 deletions src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,13 @@
WORKLOAD_VERSION_FILE_NAME = "/etc/workload-version"


class NadConfigChangedEvent(EventBase):
"""Event triggered when an existing network attachment definition is changed."""


class K8sHugePagesVolumePatchChangedEvent(EventBase):
"""Event triggered when a HugePages volume is changed."""


class UpfOperatorCharmEvents(CharmEvents):
"""Kubernetes UPF operator charm events."""

nad_config_changed = EventSource(NadConfigChangedEvent)
hugepages_volumes_config_changed = EventSource(K8sHugePagesVolumePatchChangedEvent)


Expand Down Expand Up @@ -110,12 +105,13 @@ def __init__(self, *args):
except CharmConfigInvalidError:
return
self._kubernetes_multus = KubernetesMultusCharmLib(
charm=self,
container_name=self._bessd_container_name,
cap_net_admin=True,
network_annotations_func=self._generate_network_annotations,
network_attachment_definitions_func=self._network_attachment_definitions_from_config,
refresh_event=self.on.nad_config_changed,
namespace=self._namespace,
statefulset_name=self.model.app.name,
pod_name=self._pod_name,
container_name=self._bessd_container_name,
network_annotations=self._generate_network_annotations(),
network_attachment_definitions=self._network_attachment_definitions_from_config(),
privileged=self._get_privilege_required(),
)
self._kubernetes_volumes_patch = KubernetesHugePagesPatchCharmLib(
Expand Down Expand Up @@ -544,7 +540,7 @@ def _on_config_changed(self, event: EventBase):
self.k8s_service.create()
if not self._kubernetes_multus.multus_is_available():
return
self.on.nad_config_changed.emit()
self._kubernetes_multus.configure()
self.on.hugepages_volumes_config_changed.emit()
if self._charm_config.upf_mode == UpfMode.dpdk:
self._configure_bessd_for_dpdk()
Expand Down

0 comments on commit 39d7230

Please sign in to comment.