Skip to content

Commit f82a3d2

Browse files
Fix workload_version in status message for VM upgrade (#128)
## Issue Leftover from porting k8s implementation: it was assumed that `workload_version` file matched the currently installed workload. This is true for k8s, where workload + charm code are upgraded together, but not true for VM (where charm code upgraded on all units at once, then workload upgraded by us in charm code) Impact: incorrect workload version in status message if snap not upgraded ## Solution Save `workload_version` value in unit databag when saving snap revision
1 parent 557f884 commit f82a3d2

File tree

2 files changed

+49
-27
lines changed

2 files changed

+49
-27
lines changed

src/machine_upgrade.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ class Upgrade(upgrade.Upgrade):
2626
@property
2727
def unit_state(self) -> typing.Optional[str]:
2828
if (
29-
self._unit_workload_version is not None
30-
and self._unit_workload_version != self._app_workload_version
29+
self._unit_workload_container_version is not None
30+
and self._unit_workload_container_version != self._app_workload_container_version
3131
):
3232
logger.debug("Unit upgrade state: outdated")
3333
return "outdated"
@@ -37,28 +37,31 @@ def unit_state(self) -> typing.Optional[str]:
3737
def unit_state(self, value: str) -> None:
3838
if value == "healthy":
3939
# Set snap revision on first install
40-
self._unit_databag["snap_revision"] = snap.REVISION
41-
logger.debug(f"Saved {snap.REVISION=} in unit databag while setting state healthy")
40+
self._unit_workload_container_version = snap.REVISION
41+
self._unit_workload_version = self._current_versions["workload"]
42+
logger.debug(
43+
f'Saved {snap.REVISION=} and {self._current_versions["workload"]=} in unit databag while setting state healthy'
44+
)
4245
# Super call
4346
upgrade.Upgrade.unit_state.fset(self, value)
4447

4548
def _get_unit_healthy_status(
4649
self, *, workload_status: typing.Optional[ops.StatusBase]
4750
) -> ops.StatusBase:
48-
if self._unit_workload_version == self._app_workload_version:
51+
if self._unit_workload_container_version == self._app_workload_container_version:
4952
if isinstance(workload_status, ops.WaitingStatus):
5053
return ops.WaitingStatus(
51-
f'Router {self._current_versions["workload"]} rev {self._unit_workload_version}'
54+
f"Router {self._unit_workload_version} rev {self._unit_workload_container_version}"
5255
)
5356
return ops.ActiveStatus(
54-
f'Router {self._current_versions["workload"]} rev {self._unit_workload_version} running'
57+
f"Router {self._unit_workload_version} rev {self._unit_workload_container_version} running"
5558
)
5659
if isinstance(workload_status, ops.WaitingStatus):
5760
return ops.WaitingStatus(
58-
f'Charmed operator upgraded. Router {self._current_versions["workload"]} rev {self._unit_workload_version}'
61+
f"Charmed operator upgraded. Router {self._unit_workload_version} rev {self._unit_workload_container_version}"
5962
)
6063
return ops.WaitingStatus(
61-
f'Charmed operator upgraded. Router {self._current_versions["workload"]} rev {self._unit_workload_version} running'
64+
f"Charmed operator upgraded. Router {self._unit_workload_version} rev {self._unit_workload_container_version} running"
6265
)
6366

6467
@property
@@ -73,7 +76,7 @@ def app_status(self) -> typing.Optional[ops.StatusBase]:
7376
return super().app_status
7477

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

8487
@property
85-
def _unit_workload_version(self) -> typing.Optional[str]:
88+
def _unit_workload_container_version(self) -> typing.Optional[str]:
8689
"""Installed snap revision for this unit"""
8790
return self._unit_databag.get("snap_revision")
8891

92+
@_unit_workload_container_version.setter
93+
def _unit_workload_container_version(self, value: str):
94+
self._unit_databag["snap_revision"] = value
95+
8996
@property
90-
def _app_workload_version(self) -> str:
97+
def _app_workload_container_version(self) -> str:
9198
"""Snap revision for current charm code"""
9299
return snap.REVISION
93100

101+
@property
102+
def _unit_workload_version(self) -> typing.Optional[str]:
103+
"""Installed MySQL Router version for this unit"""
104+
return self._unit_databag.get("workload_version")
105+
106+
@_unit_workload_version.setter
107+
def _unit_workload_version(self, value: str):
108+
self._unit_databag["workload_version"] = value
109+
94110
def reconcile_partition(self, *, action_event: ops.ActionEvent = None) -> None:
95111
"""Handle Juju action to confirm first upgraded unit is healthy and resume upgrade."""
96112
if action_event:
@@ -118,7 +134,7 @@ def upgrade_resumed(self, value: bool):
118134

119135
@property
120136
def authorized(self) -> bool:
121-
assert self._unit_workload_version != self._app_workload_version
137+
assert self._unit_workload_container_version != self._app_workload_container_version
122138
for index, unit in enumerate(self._sorted_units):
123139
if unit.name == self._unit.name:
124140
# Higher number units have already upgraded
@@ -128,7 +144,8 @@ def authorized(self) -> bool:
128144
return self.upgrade_resumed
129145
return True
130146
if (
131-
self._unit_workload_versions.get(unit.name) != self._app_workload_version
147+
self._unit_workload_container_versions.get(unit.name)
148+
!= self._app_workload_container_version
132149
or self._peer_relation.data[unit].get("state") != "healthy"
133150
):
134151
# Waiting for higher number units to upgrade
@@ -139,5 +156,8 @@ def upgrade_unit(self, *, workload_: workload.Workload, tls: bool) -> None:
139156
logger.debug(f"Upgrading {self.authorized=}")
140157
self.unit_state = "upgrading"
141158
workload_.upgrade(unit=self._unit, tls=tls)
142-
self._unit_databag["snap_revision"] = snap.REVISION
143-
logger.debug(f"Saved {snap.REVISION=} in unit databag after upgrade")
159+
self._unit_workload_container_version = snap.REVISION
160+
self._unit_workload_version = self._current_versions["workload"]
161+
logger.debug(
162+
f'Saved {snap.REVISION=} and {self._current_versions["workload"]=} in unit databag after upgrade'
163+
)

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)