Skip to content

Commit 996ba1e

Browse files
Merge branch 'main' into feature/external_connectivity
2 parents 1b0bb19 + 7f6947d commit 996ba1e

File tree

5 files changed

+67
-31
lines changed

5 files changed

+67
-31
lines changed

lib/charms/operator_libs_linux/v2/snap.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383

8484
# Increment this PATCH version before using `charmcraft publish-lib` or reset
8585
# to 0 if you are raising the major API version
86-
LIBPATCH = 4
86+
LIBPATCH = 5
8787

8888

8989
# Regex to locate 7-bit C1 ANSI sequences
@@ -580,10 +580,17 @@ def ensure(
580580
# We are installing or refreshing a snap.
581581
if self._state not in (SnapState.Present, SnapState.Latest):
582582
# The snap is not installed, so we install it.
583+
logger.info(
584+
"Installing snap %s, revision %s, tracking %s", self._name, revision, channel
585+
)
583586
self._install(channel, cohort, revision)
584587
else:
585588
# The snap is installed, but we are changing it (e.g., switching channels).
589+
logger.info(
590+
"Refreshing snap %s, revision %s, tracking %s", self._name, revision, channel
591+
)
586592
self._refresh(channel=channel, cohort=cohort, revision=revision, devmode=devmode)
593+
logger.info("The snap installation completed successfully")
587594

588595
self._update_snap_apps()
589596
self._state = state

src/abstract_charm.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ def reconcile(self, event=None) -> None: # noqa: C901
247247
logger.debug("Peer relation not ready")
248248
return
249249
workload_ = self.get_workload(event=event)
250+
if self._unit_lifecycle.authorized_leader and not self._upgrade.in_progress:
251+
# Run before checking `self._upgrade.is_compatible` in case incompatible upgrade was
252+
# forced & completed on all units.
253+
self._upgrade.set_versions_in_app_databag()
250254
if self._upgrade.unit_state == "restarting": # Kubernetes only
251255
if not self._upgrade.is_compatible:
252256
logger.info(
@@ -324,8 +328,6 @@ def reconcile(self, event=None) -> None: # noqa: C901
324328
self._upgrade.unit_state = "healthy"
325329
if self._unit_lifecycle.authorized_leader:
326330
self._upgrade.reconcile_partition()
327-
if not self._upgrade.in_progress:
328-
self._upgrade.set_versions_in_app_databag()
329331
self.set_status(event=event)
330332
except server_exceptions.Error as e:
331333
# If not for `unit=False`, another `server_exceptions.Error` could be thrown here

src/machine_charm.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ def _on_upgrade_charm(self, _) -> None:
149149
# Only call `reconcile` on leader unit to avoid race conditions with `upgrade_resumed`
150150
self.reconcile()
151151

152+
def _on_resume_upgrade_action(self, event: ops.ActionEvent) -> None:
153+
super()._on_resume_upgrade_action(event)
154+
# If next to upgrade, upgrade leader unit
155+
self.reconcile()
156+
152157
def _on_force_upgrade_action(self, event: ops.ActionEvent) -> None:
153158
if not self._upgrade or not self._upgrade.in_progress:
154159
message = "No upgrade in progress"

src/machine_upgrade.py

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class Upgrade(upgrade.Upgrade):
2929
@property
3030
def unit_state(self) -> typing.Optional[str]:
3131
if (
32-
self._unit_workload_version is not None
33-
and self._unit_workload_version != self._app_workload_version
32+
self._unit_workload_container_version is not None
33+
and self._unit_workload_container_version != self._app_workload_container_version
3434
):
3535
logger.debug("Unit upgrade state: outdated")
3636
return "outdated"
@@ -40,28 +40,31 @@ def unit_state(self) -> typing.Optional[str]:
4040
def unit_state(self, value: str) -> None:
4141
if value == "healthy":
4242
# Set snap revision on first install
43-
self._unit_databag["snap_revision"] = snap.REVISION
44-
logger.debug(f"Saved {snap.REVISION=} in unit databag while setting state healthy")
43+
self._unit_workload_container_version = snap.REVISION
44+
self._unit_workload_version = self._current_versions["workload"]
45+
logger.debug(
46+
f'Saved {snap.REVISION=} and {self._current_versions["workload"]=} in unit databag while setting state healthy'
47+
)
4548
# Super call
4649
upgrade.Upgrade.unit_state.fset(self, value)
4750

4851
def _get_unit_healthy_status(
4952
self, *, workload_status: typing.Optional[ops.StatusBase]
5053
) -> ops.StatusBase:
51-
if self._unit_workload_version == self._app_workload_version:
54+
if self._unit_workload_container_version == self._app_workload_container_version:
5255
if isinstance(workload_status, ops.WaitingStatus):
5356
return ops.WaitingStatus(
54-
f'Router {self._current_versions["workload"]} rev {self._unit_workload_version}'
57+
f'Router {self._unit_workload_version}; Snap rev {self._unit_workload_container_version}; Charmed operator {self._current_versions["charm"]}'
5558
)
5659
return ops.ActiveStatus(
57-
f'Router {self._current_versions["workload"]} rev {self._unit_workload_version} running'
60+
f'Router {self._unit_workload_version} running; Snap rev {self._unit_workload_container_version}; Charmed operator {self._current_versions["charm"]}'
5861
)
5962
if isinstance(workload_status, ops.WaitingStatus):
6063
return ops.WaitingStatus(
61-
f'Charmed operator upgraded. Router {self._current_versions["workload"]} rev {self._unit_workload_version}'
64+
f'Router {self._unit_workload_version}; Snap rev {self._unit_workload_container_version} (outdated); Charmed operator {self._current_versions["charm"]}'
6265
)
63-
return ops.WaitingStatus(
64-
f'Charmed operator upgraded. Router {self._current_versions["workload"]} rev {self._unit_workload_version} running'
66+
return ops.ActiveStatus(
67+
f'Router {self._unit_workload_version} running; Snap rev {self._unit_workload_container_version} (outdated); Charmed operator {self._current_versions["charm"]}'
6568
)
6669

6770
@property
@@ -76,7 +79,7 @@ def app_status(self) -> typing.Optional[ops.StatusBase]:
7679
return super().app_status
7780

7881
@property
79-
def _unit_workload_versions(self) -> typing.Dict[str, str]:
82+
def _unit_workload_container_versions(self) -> typing.Dict[str, str]:
8083
"""{Unit name: installed snap revision}"""
8184
versions = {}
8285
for unit in self._sorted_units:
@@ -85,15 +88,28 @@ def _unit_workload_versions(self) -> typing.Dict[str, str]:
8588
return versions
8689

8790
@property
88-
def _unit_workload_version(self) -> typing.Optional[str]:
91+
def _unit_workload_container_version(self) -> typing.Optional[str]:
8992
"""Installed snap revision for this unit"""
9093
return self._unit_databag.get("snap_revision")
9194

95+
@_unit_workload_container_version.setter
96+
def _unit_workload_container_version(self, value: str):
97+
self._unit_databag["snap_revision"] = value
98+
9299
@property
93-
def _app_workload_version(self) -> str:
100+
def _app_workload_container_version(self) -> str:
94101
"""Snap revision for current charm code"""
95102
return snap.REVISION
96103

104+
@property
105+
def _unit_workload_version(self) -> typing.Optional[str]:
106+
"""Installed MySQL Router version for this unit"""
107+
return self._unit_databag.get("workload_version")
108+
109+
@_unit_workload_version.setter
110+
def _unit_workload_version(self, value: str):
111+
self._unit_databag["workload_version"] = value
112+
97113
def reconcile_partition(self, *, action_event: ops.ActionEvent = None) -> None:
98114
"""Handle Juju action to confirm first upgraded unit is healthy and resume upgrade."""
99115
if action_event:
@@ -121,7 +137,7 @@ def upgrade_resumed(self, value: bool):
121137

122138
@property
123139
def authorized(self) -> bool:
124-
assert self._unit_workload_version != self._app_workload_version
140+
assert self._unit_workload_container_version != self._app_workload_container_version
125141
for index, unit in enumerate(self._sorted_units):
126142
if unit.name == self._unit.name:
127143
# Higher number units have already upgraded
@@ -131,7 +147,8 @@ def authorized(self) -> bool:
131147
return self.upgrade_resumed
132148
return True
133149
if (
134-
self._unit_workload_versions.get(unit.name) != self._app_workload_version
150+
self._unit_workload_container_versions.get(unit.name)
151+
!= self._app_workload_container_version
135152
or self._peer_relation.data[unit].get("state") != "healthy"
136153
):
137154
# Waiting for higher number units to upgrade
@@ -148,5 +165,8 @@ def upgrade_unit(
148165
logger.debug(f"Upgrading {self.authorized=}")
149166
self.unit_state = "upgrading"
150167
workload_.upgrade(unit=self._unit, tls=tls, exporter_config=exporter_config)
151-
self._unit_databag["snap_revision"] = snap.REVISION
152-
logger.debug(f"Saved {snap.REVISION=} in unit databag after upgrade")
168+
self._unit_workload_container_version = snap.REVISION
169+
self._unit_workload_version = self._current_versions["workload"]
170+
logger.debug(
171+
f'Saved {snap.REVISION=} and {self._current_versions["workload"]=} in unit databag after upgrade'
172+
)

src/upgrade.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,12 @@ def is_compatible(self) -> bool:
113113

114114
@property
115115
def in_progress(self) -> bool:
116-
logger.debug(f"{self._app_workload_version=} {self._unit_workload_versions=}")
116+
logger.debug(
117+
f"{self._app_workload_container_version=} {self._unit_workload_container_versions=}"
118+
)
117119
return any(
118-
version != self._app_workload_version
119-
for version in self._unit_workload_versions.values()
120+
version != self._app_workload_container_version
121+
for version in self._unit_workload_container_versions.values()
120122
)
121123

122124
@property
@@ -179,28 +181,28 @@ def upgrade_resumed(self) -> bool:
179181

180182
@property
181183
@abc.abstractmethod
182-
def _unit_workload_versions(self) -> typing.Dict[str, str]:
183-
"""{Unit name: unique identifier for unit's workload version}
184+
def _unit_workload_container_versions(self) -> typing.Dict[str, str]:
185+
"""{Unit name: unique identifier for unit's workload container version}
184186
185187
If and only if this version changes, the workload will restart (during upgrade or
186188
rollback).
187189
188190
On Kubernetes, the workload & charm are upgraded together
189191
On machines, the charm is upgraded before the workload
190192
191-
This identifier should be comparable to `_app_workload_version` to determine if the unit &
192-
app are the same workload version.
193+
This identifier should be comparable to `_app_workload_container_version` to determine if
194+
the unit & app are the same workload container version.
193195
"""
194196

195197
@property
196198
@abc.abstractmethod
197-
def _app_workload_version(self) -> str:
198-
"""Unique identifier for the app's workload version
199+
def _app_workload_container_version(self) -> str:
200+
"""Unique identifier for the app's workload container version
199201
200202
This should match the workload version in the current Juju app charm version.
201203
202-
This identifier should be comparable to `_get_unit_workload_version` to determine if the
203-
app & unit are the same workload version.
204+
This identifier should be comparable to `_unit_workload_container_versions` to determine if
205+
the app & unit are the same workload container version.
204206
"""
205207

206208
@abc.abstractmethod

0 commit comments

Comments
 (0)