[openstack-hypervisor] error out on snap installation failure

When the openstack-hypervisor snap fails to install, then set
the unit status to error instead of blocked.

Closes-Bug: #2065944.

Change-Id: I0b3817c8e8321e5bfd8eaabe63646c9cd48cdf36
This commit is contained in:
Ahmad Hassan
2025-01-27 18:41:14 +05:00
parent 03000df1de
commit b3387c4ff1
4 changed files with 39 additions and 4 deletions
+13 -2
View File
@@ -71,6 +71,10 @@ DATA_BINDING = "data"
MTLS_USAGES = {x509.OID_SERVER_AUTH, x509.OID_CLIENT_AUTH}
class SnapInstallationError(Exception):
"""Custom exception for snap installation failure errors."""
class HypervisorError(Exception):
"""Custom exception for Hypervisor errors."""
@@ -217,7 +221,10 @@ class HypervisorOperatorCharm(sunbeam_charm.OSBaseOperatorCharm):
def _on_install(self, _: ops.InstallEvent):
"""Run install on this unit."""
self.ensure_snap_present()
with sunbeam_guard.guard(
self, "Executing install hook event handler", False
):
self.ensure_snap_present()
@property
def migration_address(self) -> Optional[str]:
@@ -490,12 +497,16 @@ class HypervisorOperatorCharm(sunbeam_charm.OSBaseOperatorCharm):
hypervisor.ensure(
snap.SnapState.Latest, channel=config("snap-channel")
)
except snap.SnapError as e:
except (snap.SnapError, snap.SnapNotFoundError) as e:
logger.error(
"An exception occurred when installing openstack-hypervisor. Reason: %s",
e.message,
)
raise SnapInstallationError(
"openstack-hypervisor installation failed"
)
@functools.cache
def get_snap_cache(self) -> snap.SnapCache:
"""Return snap cache."""
@@ -21,6 +21,7 @@ from unittest.mock import (
)
import charm
import charms.operator_libs_linux.v2.snap as snap
import ops
import ops.testing
import ops_sunbeam.test_utils as test_utils
@@ -289,6 +290,13 @@ class TestCharm(test_utils.CharmTestCase):
}
hypervisor_snap_mock.set.assert_any_call(expect_settings, typed=True)
def test_openstack_hypervisor_snap_not_installed(self):
"""Check action raises SnapNotFoundError if openstack-hypervisor snap is not installed."""
self.harness.begin()
self.snap.SnapCache.side_effect = snap.SnapNotFoundError
with self.assertRaises(snap.SnapNotFoundError):
self.harness.run_action("list-nics")
def test_list_nics_snap_not_installed(self):
"""Check action raises ActionFailed if snap is not installed."""
self.harness.begin()
+8 -2
View File
@@ -63,6 +63,10 @@ def _identity(x: bool) -> bool:
return x
class SnapInstallationError(Exception):
"""Custom exception for snap installation failure errors."""
@sunbeam_tracing.trace_type
class ClusterCertificatesHandler(sunbeam_rhandlers.TlsCertificatesHandler):
"""Handler for certificates interface."""
@@ -204,7 +208,8 @@ class SunbeamClusterdCharm(sunbeam_charm.OSBaseOperatorCharm):
def _on_install(self, event: ops.InstallEvent) -> None:
"""Handle install event."""
try:
self.ensure_snap_present()
with sunbeam_guard.guard(self, "Ensure snap installation", False):
self.ensure_snap_present()
except TimeoutError:
logger.debug("Snap installation failed, retrying.")
event.defer()
@@ -275,11 +280,12 @@ class SunbeamClusterdCharm(sunbeam_charm.OSBaseOperatorCharm):
openstack.ensure(snap.SnapState.Latest, channel=snap_channel)
self._state.channel = openstack.channel
self.set_workload_version()
except snap.SnapError as e:
except (snap.SnapError, snap.SnapNotFoundError) as e:
logger.error(
"An exception occurred when installing snap. Reason: %s",
e.message,
)
raise SnapInstallationError("openstack snap installation failed")
def set_workload_version(self):
"""Set workload version."""
@@ -15,6 +15,9 @@ import ops
import ops.testing as testing
import ops_sunbeam.test_utils as test_utils
import yaml
from charms.operator_libs_linux.v2 import (
snap,
)
class _SunbeamClusterdCharm(charm.SunbeamClusterdCharm):
@@ -59,6 +62,13 @@ class TestCharm(test_utils.CharmTestCase):
self.harness.add_network("10.0.0.10")
self.harness.begin_with_initial_hooks()
def test_openstack_snap_not_installed(self):
"""Check action raises SnapNotFoundError if openstack snap is not installed."""
self.harness.begin()
self.ensure_snap_present.side_effect = snap.SnapNotFoundError
with self.assertRaises(snap.SnapNotFoundError):
self.harness.charm.on.install.emit()
def test_initial_bootstrap(self):
"""Test charm is bootstrapped."""
self.initial_setup()