Add library ceilometer-service
Add new library ceilometer-service. Update ceilometer charm to handle the interface provider events. Change-Id: Ibe49fa91dbf224dae98f6258fbd8ec22c7ccd3be
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
"""CeilometerServiceProvides and Requires module.
|
||||
|
||||
This library contains the Requires and Provides classes for handling
|
||||
the ceilometer_service interface.
|
||||
|
||||
Import `CeilometerServiceRequires` in your charm, with the charm object and the
|
||||
relation name:
|
||||
- self
|
||||
- "ceilometer_service"
|
||||
|
||||
Two events are also available to respond to:
|
||||
- config_changed
|
||||
- goneaway
|
||||
|
||||
A basic example showing the usage of this relation follows:
|
||||
|
||||
```
|
||||
from charms.ceilometer_k8s.v0.ceilometer_service import (
|
||||
CeilometerServiceRequires
|
||||
)
|
||||
|
||||
class CeilometerServiceClientCharm(CharmBase):
|
||||
def __init__(self, *args):
|
||||
super().__init__(*args)
|
||||
# CeilometerService Requires
|
||||
self.ceilometer_service = CeilometerServiceRequires(
|
||||
self, "ceilometer_service",
|
||||
)
|
||||
self.framework.observe(
|
||||
self.ceilometer_service.on.config_changed,
|
||||
self._on_ceilometer_service_config_changed
|
||||
)
|
||||
self.framework.observe(
|
||||
self.ceilometer_service.on.goneaway,
|
||||
self._on_ceiometer_service_goneaway
|
||||
)
|
||||
|
||||
def _on_ceilometer_service_config_changed(self, event):
|
||||
'''React to the Ceilometer service config changed event.
|
||||
|
||||
This event happens when CeilometerService relation is added to the
|
||||
model and relation data is changed.
|
||||
'''
|
||||
# Do something with the configuration provided by relation.
|
||||
pass
|
||||
|
||||
def _on_ceilometer_service_goneaway(self, event):
|
||||
'''React to the CeilometerService goneaway event.
|
||||
|
||||
This event happens when CeilometerService relation is removed.
|
||||
'''
|
||||
# CeilometerService Relation has goneaway.
|
||||
pass
|
||||
```
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import (
|
||||
Optional,
|
||||
)
|
||||
|
||||
from ops.charm import (
|
||||
CharmBase,
|
||||
RelationBrokenEvent,
|
||||
RelationChangedEvent,
|
||||
RelationEvent,
|
||||
)
|
||||
from ops.framework import (
|
||||
EventSource,
|
||||
Object,
|
||||
ObjectEvents,
|
||||
)
|
||||
from ops.model import (
|
||||
Relation,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# The unique Charmhub library identifier, never change it
|
||||
LIBID = "fcbb94e7a18740729eaf9e2c3b90017f"
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
class CeilometerConfigRequestEvent(RelationEvent):
|
||||
"""CeilometerConfigRequest Event."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class CeilometerServiceProviderEvents(ObjectEvents):
|
||||
"""Events class for `on`."""
|
||||
|
||||
config_request = EventSource(CeilometerConfigRequestEvent)
|
||||
|
||||
|
||||
class CeilometerServiceProvides(Object):
|
||||
"""CeilometerServiceProvides class."""
|
||||
|
||||
on = CeilometerServiceProviderEvents()
|
||||
|
||||
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_ceilometer_service_relation_changed,
|
||||
)
|
||||
|
||||
def _on_ceilometer_service_relation_changed(
|
||||
self, event: RelationChangedEvent
|
||||
):
|
||||
"""Handle CeilometerService relation changed."""
|
||||
logging.debug("CeilometerService relation changed")
|
||||
self.on.config_request.emit(event.relation)
|
||||
|
||||
def set_config(
|
||||
self, relation: Optional[Relation], telemetry_secret: str
|
||||
) -> None:
|
||||
"""Set ceilometer configuration on the relation."""
|
||||
if not self.charm.unit.is_leader():
|
||||
logging.debug("Not a leader unit, skipping set config")
|
||||
return
|
||||
|
||||
# If relation is not provided send config to all the related
|
||||
# applications. This happens usually when config data is
|
||||
# updated by provider and wants to send the data to all
|
||||
# related applications
|
||||
if relation is None:
|
||||
logging.debug(
|
||||
"Sending config to all related applications of relation"
|
||||
f"{self.relation_name}"
|
||||
)
|
||||
for relation in self.framework.model.relations[self.relation_name]:
|
||||
relation.data[self.charm.app][
|
||||
"telemetry-secret"
|
||||
] = telemetry_secret
|
||||
else:
|
||||
logging.debug(
|
||||
f"Sending config on relation {relation.app.name} "
|
||||
f"{relation.name}/{relation.id}"
|
||||
)
|
||||
relation.data[self.charm.app][
|
||||
"telemetry-secret"
|
||||
] = telemetry_secret
|
||||
|
||||
|
||||
class CeilometerConfigChangedEvent(RelationEvent):
|
||||
"""CeilometerConfigChanged Event."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class CeilometerServiceGoneAwayEvent(RelationEvent):
|
||||
"""CeilometerServiceGoneAway Event."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class CeilometerServiceRequirerEvents(ObjectEvents):
|
||||
"""Events class for `on`."""
|
||||
|
||||
config_changed = EventSource(CeilometerConfigChangedEvent)
|
||||
goneaway = EventSource(CeilometerServiceGoneAwayEvent)
|
||||
|
||||
|
||||
class CeilometerServiceRequires(Object):
|
||||
"""CeilometerServiceRequires class."""
|
||||
|
||||
on = CeilometerServiceRequirerEvents()
|
||||
|
||||
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_ceilometer_service_relation_changed,
|
||||
)
|
||||
self.framework.observe(
|
||||
self.charm.on[relation_name].relation_broken,
|
||||
self._on_ceilometer_service_relation_broken,
|
||||
)
|
||||
|
||||
def _on_ceilometer_service_relation_changed(
|
||||
self, event: RelationChangedEvent
|
||||
):
|
||||
"""Handle CeilometerService relation changed."""
|
||||
logging.debug("CeilometerService config data changed")
|
||||
self.on.config_changed.emit(event.relation)
|
||||
|
||||
def _on_ceilometer_service_relation_broken(
|
||||
self, event: RelationBrokenEvent
|
||||
):
|
||||
"""Handle CeilometerService relation changed."""
|
||||
logging.debug("CeilometerService on_broken")
|
||||
self.on.goneaway.emit(event.relation)
|
||||
|
||||
@property
|
||||
def _ceilometer_service_rel(self) -> Optional[Relation]:
|
||||
"""The ceilometer service relation."""
|
||||
return self.framework.model.get_relation(self.relation_name)
|
||||
|
||||
def get_remote_app_data(self, key: str) -> Optional[str]:
|
||||
"""Return the value for the given key from remote app data."""
|
||||
if self._ceilometer_service_rel:
|
||||
data = self._ceilometer_service_rel.data[
|
||||
self._ceilometer_service_rel.app
|
||||
]
|
||||
return data.get(key)
|
||||
|
||||
return None
|
||||
|
||||
@property
|
||||
def telemetry_secret(self) -> Optional[str]:
|
||||
"""Return the telemetry_secret."""
|
||||
return self.get_remote_app_data("telemetry-secret")
|
@@ -34,6 +34,10 @@ resources:
|
||||
description: OCI image for OpenStack ceilometer
|
||||
upstream-source: ghcr.io/openstack-snaps/ceilometer-consolidated:2023.1
|
||||
|
||||
provides:
|
||||
ceilometer-service:
|
||||
interface: ceilometer
|
||||
|
||||
requires:
|
||||
amqp:
|
||||
interface: rabbitmq
|
||||
|
@@ -21,15 +21,22 @@ This charm provide Ceilometer services as part of an OpenStack deployment
|
||||
import logging
|
||||
import uuid
|
||||
from typing import (
|
||||
Callable,
|
||||
List,
|
||||
)
|
||||
|
||||
import ops.framework
|
||||
import ops_sunbeam.charm as sunbeam_charm
|
||||
import ops_sunbeam.container_handlers as container_handlers
|
||||
import ops_sunbeam.container_handlers as sunbeam_chandlers
|
||||
import ops_sunbeam.core as sunbeam_core
|
||||
import ops_sunbeam.relation_handlers as sunbeam_rhandlers
|
||||
from charms.ceilometer_k8s.v0.ceilometer_service import (
|
||||
CeilometerConfigRequestEvent,
|
||||
CeilometerServiceProvides,
|
||||
)
|
||||
from ops.charm import (
|
||||
ActionEvent,
|
||||
CharmBase,
|
||||
)
|
||||
from ops.main import (
|
||||
main,
|
||||
@@ -41,7 +48,41 @@ CEILOMETER_CENTRAL_CONTAINER = "ceilometer-central"
|
||||
CEILOMETER_NOTIFICATION_CONTAINER = "ceilometer-notification"
|
||||
|
||||
|
||||
class CeilometerCentralPebbleHandler(container_handlers.ServicePebbleHandler):
|
||||
class CeilometerServiceProvidesHandler(sunbeam_rhandlers.RelationHandler):
|
||||
"""Handler for ceilometer service relation."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
charm: CharmBase,
|
||||
relation_name: str,
|
||||
callback_f: Callable,
|
||||
):
|
||||
super().__init__(charm, relation_name, callback_f)
|
||||
|
||||
def setup_event_handler(self):
|
||||
"""Configure event handlers for an Ceilometer service relation."""
|
||||
logger.debug("Setting up Ceilometer service event handler")
|
||||
svc = CeilometerServiceProvides(
|
||||
self.charm,
|
||||
self.relation_name,
|
||||
)
|
||||
self.framework.observe(
|
||||
svc.on.config_request,
|
||||
self._on_config_request,
|
||||
)
|
||||
return svc
|
||||
|
||||
def _on_config_request(self, event: CeilometerConfigRequestEvent) -> None:
|
||||
"""Handle Config request event."""
|
||||
self.callback_f(event)
|
||||
|
||||
@property
|
||||
def ready(self) -> bool:
|
||||
"""Report if relation is ready."""
|
||||
return True
|
||||
|
||||
|
||||
class CeilometerCentralPebbleHandler(sunbeam_chandlers.ServicePebbleHandler):
|
||||
"""Pebble handler for ceilometer-central service."""
|
||||
|
||||
def get_layer(self) -> dict:
|
||||
@@ -77,7 +118,7 @@ class CeilometerCentralPebbleHandler(container_handlers.ServicePebbleHandler):
|
||||
|
||||
|
||||
class CeilometerNotificationPebbleHandler(
|
||||
container_handlers.ServicePebbleHandler
|
||||
sunbeam_chandlers.ServicePebbleHandler
|
||||
):
|
||||
"""Pebble handler for ceilometer-notification service."""
|
||||
|
||||
@@ -163,6 +204,7 @@ class CeilometerOperatorCharm(sunbeam_charm.OSBaseOperatorCharmK8S):
|
||||
if self.unit.is_leader():
|
||||
logger.debug("Creating metering secret")
|
||||
self.set_shared_meteringsecret()
|
||||
self.set_config_on_update()
|
||||
else:
|
||||
logger.debug("Metadata secret not ready")
|
||||
return
|
||||
@@ -191,7 +233,7 @@ class CeilometerOperatorCharm(sunbeam_charm.OSBaseOperatorCharmK8S):
|
||||
]
|
||||
return _cconfigs
|
||||
|
||||
def get_pebble_handlers(self) -> List[container_handlers.PebbleHandler]:
|
||||
def get_pebble_handlers(self) -> List[sunbeam_chandlers.PebbleHandler]:
|
||||
"""Pebble handlers for the operator."""
|
||||
return [
|
||||
CeilometerCentralPebbleHandler(
|
||||
@@ -212,6 +254,41 @@ class CeilometerOperatorCharm(sunbeam_charm.OSBaseOperatorCharmK8S):
|
||||
),
|
||||
]
|
||||
|
||||
def get_relation_handlers(
|
||||
self, handlers: List[sunbeam_rhandlers.RelationHandler] = None
|
||||
) -> List[sunbeam_rhandlers.RelationHandler]:
|
||||
"""Relation handlers for the service."""
|
||||
handlers = handlers or []
|
||||
if self.can_add_handler("ceilometer-service", handlers):
|
||||
self.config_svc = CeilometerServiceProvidesHandler(
|
||||
self,
|
||||
"ceilometer-service",
|
||||
self.set_config_from_event,
|
||||
)
|
||||
handlers.append(self.config_svc)
|
||||
|
||||
return super().get_relation_handlers(handlers)
|
||||
|
||||
def set_config_from_event(self, event: ops.framework.EventBase) -> None:
|
||||
"""Set config in relation data."""
|
||||
telemetry_secret = self.get_shared_meteringsecret()
|
||||
if telemetry_secret:
|
||||
self.config_svc.interface.set_config(
|
||||
relation=event.relation, telemetry_secret=telemetry_secret
|
||||
)
|
||||
else:
|
||||
logging.debug("Telemetry secret not yet set, not sending config")
|
||||
|
||||
def set_config_on_update(self) -> None:
|
||||
"""Set config on relation on update of local data."""
|
||||
telemetry_secret = self.get_shared_meteringsecret()
|
||||
if telemetry_secret:
|
||||
self.config_svc.interface.set_config(
|
||||
relation=None, telemetry_secret=telemetry_secret
|
||||
)
|
||||
else:
|
||||
logging.debug("Telemetry secret not yet set, not sending config")
|
||||
|
||||
def _ceilometer_upgrade_action(self, event: ActionEvent) -> None:
|
||||
"""Run ceilometer-upgrade.
|
||||
|
||||
|
Reference in New Issue
Block a user