Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions sunbeam-python/sunbeam/core/juju.py
Original file line number Diff line number Diff line change
Expand Up @@ -2076,6 +2076,61 @@ def get_external_controllers(self) -> list:

return external_controllers

def get_controller_config(self, controller_name: str) -> dict | None:
"""Return connection details for a registered controller.

Uses ``get_controller`` for the API endpoint and CA certificate,
and ``~/.local/share/juju/accounts.yaml`` for credentials.
Only returns a result if the controller is registered locally.

:return: A dict with keys ``controller_addresses``, ``username``,
``password``, ``ca_certificate``, or ``None``.
"""
try:
ctrl = self.get_controller(controller_name)
except ControllerNotFoundException:
LOG.warning(
"Controller %r is not registered as Juju controller. "
"Register it with `juju register` first.",
controller_name,
)
return None

details = ctrl.get("details", {})
api_endpoints = details.get("api-endpoints")
ca_cert = details.get("ca-cert")
if not api_endpoints or not ca_cert:
return None

try:
juju_data_dir = Path(
os.environ.get(
"JUJU_DATA", f"{os.environ.get('SNAP_REAL_HOME')}/.local/share/juju"
)
)
accounts_data = yaml.safe_load(
(juju_data_dir / "accounts.yaml").read_text()
)
except (FileNotFoundError, yaml.YAMLError):
LOG.debug("No local accounts.yaml found for %r", controller_name)
return None

acct = accounts_data.get("controllers", {}).get(controller_name)
if not acct:
return None

user = acct.get("user")
password = acct.get("password")
if not user or not password:
return None

return {
"controller_addresses": api_endpoints[0],
"username": user,
"password": password,
"ca_certificate": ca_cert,
}

def get_controller(self, controller: str) -> dict:
"""Get controller definition."""
try:
Expand Down Expand Up @@ -2375,3 +2430,24 @@ def run_action(
except ActionFailedException as e:
LOG.debug("Action %r failed on node %r: %r", action_name, node, e)
raise e


def split_controller_from_offer_url(url: str) -> tuple[str | None, str]:
"""Split the controller prefix from an offer URL.

Juju offer URLs have the form:
``[<controller>:][<owner>/]<model>.<application>[:<endpoint>]``

Returns a tuple of ``(controller, offer_url_without_controller)``.
The controller is ``None`` if the URL does not include a controller prefix.

:param url: The offer URL to split.
:return: A tuple of (controller, offer_url_without_controller).
:raises ValueError: If the URL is not a valid offer URL.
"""
parts = url.split(":", 1)
if len(parts) == 2 and "." in parts[0]:
return None, url
if len(parts) == 2:
return parts[0], parts[1]
return None, url
16 changes: 16 additions & 0 deletions sunbeam-python/sunbeam/features/baremetal/steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,22 @@ def __init__(
self.model = OPENSTACK_MODEL
self.apps = apps

def is_skip(self, context: StepContext) -> Result:
"""Skip the temp-url-secret action when Glance uses external S3.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/temp-url-secret/set-temp-url-secret/

set-temp-url-secret is the action per the ironic charmcraft.yaml


With an S3-backed Glance, ironic-conductor serves deploy images from the
S3 backend through its local HTTP server and does not rely on Ceph
RadosGW Swift temporary URLs, so no temp-url secret is required.
"""
from sunbeam.steps.openstack import is_glance_s3_storage_enabled

if is_glance_s3_storage_enabled(self.deployment.get_client()):
return Result(
ResultType.SKIPPED,
"Glance uses external S3 storage; temp-url secret not required.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Glance uses external S3 storage; temp-url secret not required.",
"Glance is using external S3 storage; set-temp-url-secret action not run.",

)
return Result(ResultType.COMPLETED)

def run(self, context: StepContext) -> Result:
"""Run the set-temp-url-secret action on ironic-conductor apps."""
try:
Expand Down
7 changes: 5 additions & 2 deletions sunbeam-python/sunbeam/features/telemetry/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Telemetry service

This feature provides Telemetry service for Sunbeam. It is based on OpenStack Telemetry projects [Ceilometer](https://docs.openstack.org/designate/latest/), [Aodh](https://docs.openstack.org/aodh/latest/), [Gnocchi](https://wiki.openstack.org/wiki/Gnocchi).
This feature provides Telemetry service for Sunbeam. It is based on OpenStack Telemetry projects [Ceilometer](https://docs.openstack.org/ceilometer/latest/), [Aodh](https://docs.openstack.org/aodh/latest/), [Gnocchi](https://wiki.openstack.org/wiki/Gnocchi).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This feature provides Telemetry service for Sunbeam. It is based on OpenStack Telemetry projects [Ceilometer](https://docs.openstack.org/ceilometer/latest/), [Aodh](https://docs.openstack.org/aodh/latest/), [Gnocchi](https://wiki.openstack.org/wiki/Gnocchi).
This feature provides a Telemetry service for Sunbeam. It is based on OpenStack Telemetry projects: [Ceilometer](https://docs.openstack.org/ceilometer/latest/), [Aodh](https://docs.openstack.org/aodh/latest/), and [Gnocchi](https://wiki.openstack.org/wiki/Gnocchi).


## Installation

Expand All @@ -13,11 +13,14 @@ sunbeam enable telemetry
## Contents

This feature will install the following services:

- Ceilometer: Data collection service [charm](https://opendev.org/openstack/charm-ceilometer-k8s) [ROCK](https://github.com/canonical/ubuntu-openstack-rocks/tree/main/rocks/ceilometer-consolidated)
- Aodh: Alarming service [charm](https://opendev.org/openstack/charm-aodh-k8s) [ROCK](https://github.com/canonical/ubuntu-openstack-rocks/tree/main/rocks/aodh-consolidated)
- Gnocchi: Time series database service [charm](https://opendev.org/openstack/charm-gnocchi-k8s) [ROCK](https://github.com/canonical/ubuntu-openstack-rocks/tree/main/rocks/gnocchi-consolidated)
- Ceilometer Agent: Agent on hypervisor [charm](https://opendev.org/openstack/charm-openstack-hypervisor) [SNAP](https://github.com/canonical/snap-openstack-hypervisor.git)
- MySQL Router for Designate [charm](https://github.com/canonical/mysql-router-k8s-operator) [ROCK](https://github.com/canonical/charmed-mysql-rock)
- TODO: ADD OPENSTACK EXPORTER INFO

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve TODO or create a jira card.

- MySQL Router for Aodh [charm](https://github.com/canonical/mysql-router-k8s-operator) [ROCK](https://github.com/canonical/charmed-mysql-rock)
- MySQL Router for Gnocchi [charm](https://github.com/canonical/mysql-router-k8s-operator) [ROCK](https://github.com/canonical/charmed-mysql-rock)
- MySQL Instance in the case of a multi-mysql installation (for large deployments) [charm](https://github.com/canonical/mysql-k8s-operator) [ROCK](https://github.com/canonical/charmed-mysql-rock)

Services are constituted of charms, i.e. operator code, and ROCKs, the corresponding OCI images.
Expand Down
Loading
Loading